import { BaseHttpClient } from '../http/client.ts';
import type { ArrSystemStatus, ArrDelayProfile, ArrTag, ArrMediaManagementConfig, ArrNamingConfig, ArrQualityDefinition } from './types.ts';
import { logger } from '$logger/logger.ts';

/**
 * Base client for all *arr applications
 * Extends BaseHttpClient with arr-specific features
 */
export class BaseArrClient extends BaseHttpClient {
	private apiKey: string;
	protected apiVersion: string = 'v3'; // Default to v3, can be overridden by subclasses

	constructor(url: string, apiKey: string) {
		super(url, {
			headers: {
				'X-Api-Key': apiKey
			}
		});
		this.apiKey = apiKey;
	}

	/**
	 * Test connection to the arr instance
	 * Calls /api/{version}/system/status endpoint
	 * Note: This method has built-in retry logic (3 attempts by default)
	 * @returns true if connection successful, false otherwise
	 */
	async testConnection(): Promise<boolean> {
		try {
			const status = await this.get<ArrSystemStatus>(`/api/${this.apiVersion}/system/status`);

			await logger.info(`Connection successful to ${this.baseUrl}`, {
				source: 'BaseArrClient',
				meta: {
					appName: status.appName,
					version: status.version,
					osName: status.osName
				}
			});

			return true;
		} catch (error) {
			// Only log after all retries are exhausted
			await logger.error(`Connection failed to ${this.baseUrl} after retries`, {
				source: 'BaseArrClient',
				meta: error
			});

			return false;
		}
	}

	// =========================================================================
	// Delay Profiles
	// =========================================================================

	/**
	 * Get all delay profiles
	 */
	async getDelayProfiles(): Promise<ArrDelayProfile[]> {
		return this.get<ArrDelayProfile[]>(`/api/${this.apiVersion}/delayprofile`);
	}

	/**
	 * Get a delay profile by ID
	 */
	async getDelayProfile(id: number): Promise<ArrDelayProfile> {
		return this.get<ArrDelayProfile>(`/api/${this.apiVersion}/delayprofile/${id}`);
	}

	/**
	 * Create a new delay profile
	 */
	async createDelayProfile(profile: Omit<ArrDelayProfile, 'id' | 'order'>): Promise<ArrDelayProfile> {
		return this.post<ArrDelayProfile>(`/api/${this.apiVersion}/delayprofile`, profile);
	}

	/**
	 * Update an existing delay profile
	 */
	async updateDelayProfile(id: number, profile: ArrDelayProfile): Promise<ArrDelayProfile> {
		return this.put<ArrDelayProfile>(`/api/${this.apiVersion}/delayprofile/${id}`, profile);
	}

	/**
	 * Delete a delay profile
	 */
	async deleteDelayProfile(id: number): Promise<void> {
		await this.delete(`/api/${this.apiVersion}/delayprofile/${id}`);
	}

	// =========================================================================
	// Tags
	// =========================================================================

	/**
	 * Get all tags
	 */
	async getTags(): Promise<ArrTag[]> {
		return this.get<ArrTag[]>(`/api/${this.apiVersion}/tag`);
	}

	/**
	 * Create a new tag
	 */
	async createTag(label: string): Promise<ArrTag> {
		return this.post<ArrTag>(`/api/${this.apiVersion}/tag`, { label });
	}

	// =========================================================================
	// Media Management Config
	// =========================================================================

	/**
	 * Get media management config
	 */
	async getMediaManagementConfig(): Promise<ArrMediaManagementConfig> {
		return this.get<ArrMediaManagementConfig>(`/api/${this.apiVersion}/config/mediamanagement`);
	}

	/**
	 * Update media management config
	 * Note: Must PUT to /{id} endpoint
	 */
	async updateMediaManagementConfig(config: ArrMediaManagementConfig): Promise<ArrMediaManagementConfig> {
		return this.put<ArrMediaManagementConfig>(
			`/api/${this.apiVersion}/config/mediamanagement/${config.id}`,
			config
		);
	}

	// =========================================================================
	// Naming Config
	// =========================================================================

	/**
	 * Get naming config
	 */
	async getNamingConfig(): Promise<ArrNamingConfig> {
		return this.get<ArrNamingConfig>(`/api/${this.apiVersion}/config/naming`);
	}

	/**
	 * Update naming config
	 * Note: Must PUT to /{id} endpoint
	 */
	async updateNamingConfig(config: ArrNamingConfig): Promise<ArrNamingConfig> {
		return this.put<ArrNamingConfig>(
			`/api/${this.apiVersion}/config/naming/${config.id}`,
			config
		);
	}

	// =========================================================================
	// Quality Definitions
	// =========================================================================

	/**
	 * Get all quality definitions
	 */
	async getQualityDefinitions(): Promise<ArrQualityDefinition[]> {
		return this.get<ArrQualityDefinition[]>(`/api/${this.apiVersion}/qualitydefinition`);
	}

	/**
	 * Update all quality definitions
	 * Note: PUT to /update endpoint with full array
	 */
	async updateQualityDefinitions(definitions: ArrQualityDefinition[]): Promise<ArrQualityDefinition[]> {
		return this.put<ArrQualityDefinition[]>(
			`/api/${this.apiVersion}/qualitydefinition/update`,
			definitions
		);
	}
}
