import { IPublicClientApplication } from '@azure/msal-browser';
import { getAccessToken } from './authService';
import type { AgentReview, FlaggedItem, ResolvedItem, ErrorItem } from '../types';

const API_URL = import.meta.env.VITE_BACKEND_URL || 'http://localhost:8000';

// Types for API responses
export interface CampaignResponse {
    id: string;
    name: string;
    workfront_id: string | null;
    client_lead: string | null;
    agency_lead: string | null;
    brand_guidelines: string | null;
    status: string;
    agency: string | null;
    created_at: string;
    updated_at: string;
    proofs: number;
}

export interface ProofVersionResponse {
    id: string;
    version: number;
    file_storage_key: string | null;
    thumbnail_url: string | null;
    agent_review: AgentReview | null;
    overall_status: string | null;
    workfront_id: string | null;
    created_at: string;
}

export interface ProofResponse {
    id: string;
    proof_name: string;
    channel: string | null;
    sub_channel: string | null;
    proof_type: string | null;
    workfront_id: string | null;
    created_at: string;
    versions: ProofVersionResponse[];
}

export interface AnalyticsResponse {
    total_reviews: number;
    passed: number;
    failed: number;
    errors: number;
    legal_review: number;
}

export interface FlaggedItemResponse {
    id: string;
    proof_version_id: string;
    agent_flagged: string;
    comments: string | null;
    submitter_name: string | null;
    submitter_agency: string | null;
    campaign_name: string | null;
    proof_name: string | null;
    version: number | null;
    created_at: string;
}

export interface ResolvedItemResponse {
    id: string;
    proof_version_id: string;
    agent: string;
    issue: string | null;
    resolution: string | null;
    submitter_name: string | null;
    submitter_agency: string | null;
    campaign_name: string | null;
    proof_name: string | null;
    version: number | null;
    created_at: string;
}

export interface ErrorItemResponse {
    id: string;
    proof_version_id: string;
    error_summary: string | null;
    campaign_name: string | null;
    proof_name: string | null;
    version: number | null;
    created_at: string;
}

class ApiService {
    private msalInstance: IPublicClientApplication | null = null;

    setMsalInstance(instance: IPublicClientApplication) {
        this.msalInstance = instance;
    }

    private async getHeaders(): Promise<HeadersInit> {
        const headers: HeadersInit = {
            'Content-Type': 'application/json',
        };

        if (this.msalInstance) {
            const token = await getAccessToken(this.msalInstance);
            if (token) {
                headers['Authorization'] = `Bearer ${token}`;
            }
        }

        return headers;
    }

    private async fetch<T>(endpoint: string, options: RequestInit = {}): Promise<T> {
        const headers = await this.getHeaders();
        const response = await fetch(`${API_URL}/api${endpoint}`, {
            ...options,
            headers: {
                ...headers,
                ...options.headers,
            },
        });

        if (!response.ok) {
            const errorData = await response.json().catch(() => ({}));
            throw new Error(errorData.detail || `HTTP ${response.status}: ${response.statusText}`);
        }

        // Handle 204 No Content
        if (response.status === 204) {
            return undefined as T;
        }

        return response.json();
    }

    // Campaign endpoints
    async getCampaigns(): Promise<CampaignResponse[]> {
        return this.fetch<CampaignResponse[]>('/campaigns');
    }

    async getCampaign(id: string): Promise<CampaignResponse> {
        return this.fetch<CampaignResponse>(`/campaigns/${id}`);
    }

    async createCampaign(data: {
        name: string;
        workfront_id?: string;
        client_lead?: string;
        agency_lead?: string;
        brand_guidelines?: string;
    }): Promise<CampaignResponse> {
        return this.fetch<CampaignResponse>('/campaigns', {
            method: 'POST',
            body: JSON.stringify(data),
        });
    }

    async updateCampaign(id: string, data: {
        name?: string;
        workfront_id?: string;
        client_lead?: string;
        agency_lead?: string;
        brand_guidelines?: string;
        status?: string;
    }): Promise<CampaignResponse> {
        return this.fetch<CampaignResponse>(`/campaigns/${id}`, {
            method: 'PUT',
            body: JSON.stringify(data),
        });
    }

    async deleteCampaign(id: string): Promise<void> {
        return this.fetch<void>(`/campaigns/${id}`, {
            method: 'DELETE',
        });
    }

    // Proof endpoints
    async getProofs(campaignId: string): Promise<ProofResponse[]> {
        return this.fetch<ProofResponse[]>(`/campaigns/${campaignId}/proofs`);
    }

    async getProof(id: string): Promise<ProofResponse> {
        return this.fetch<ProofResponse>(`/proofs/${id}`);
    }

    async deleteProof(id: string): Promise<void> {
        return this.fetch<void>(`/proofs/${id}`, {
            method: 'DELETE',
        });
    }

    // Audit endpoints
    async flagProofVersion(proofId: string, version: number, data: {
        agent_flagged: string;
        comments?: string;
    }): Promise<FlaggedItemResponse> {
        return this.fetch<FlaggedItemResponse>(`/proofs/${proofId}/versions/${version}/flag`, {
            method: 'POST',
            body: JSON.stringify({
                proof_version_id: '', // Will be set by backend
                ...data,
            }),
        });
    }

    async resolveProofVersion(proofId: string, version: number, data: {
        agent: string;
        issue?: string;
        resolution?: string;
    }): Promise<ResolvedItemResponse> {
        return this.fetch<ResolvedItemResponse>(`/proofs/${proofId}/versions/${version}/resolve`, {
            method: 'POST',
            body: JSON.stringify({
                proof_version_id: '', // Will be set by backend
                ...data,
            }),
        });
    }

    async getFlaggedItems(): Promise<FlaggedItemResponse[]> {
        return this.fetch<FlaggedItemResponse[]>('/audit/flagged');
    }

    async getResolvedItems(): Promise<ResolvedItemResponse[]> {
        return this.fetch<ResolvedItemResponse[]>('/audit/resolved');
    }

    async getErrorItems(): Promise<ErrorItemResponse[]> {
        return this.fetch<ErrorItemResponse[]>('/audit/errors');
    }

    // Analytics endpoint
    async getAnalytics(): Promise<AnalyticsResponse> {
        return this.fetch<AnalyticsResponse>('/analytics');
    }

    // Helper to convert API response to frontend format
    convertCampaignToFrontend(campaign: CampaignResponse) {
        return {
            name: campaign.name,
            workfrontId: campaign.workfront_id || '',
            clientLead: campaign.client_lead || '',
            agency: campaign.agency || '',
            agencyLead: campaign.agency_lead || '',
            proofs: campaign.proofs,
            status: campaign.status as 'In Progress' | 'Completed',
            lastModified: campaign.updated_at,
            brandGuidelines: campaign.brand_guidelines || 'Barclays',
            _id: campaign.id,
        };
    }

    convertProofToFrontend(proof: ProofResponse) {
        const latestVersion = proof.versions[0];
        return {
            proofName: proof.proof_name,
            channel: proof.channel || '',
            subChannel: proof.sub_channel || '',
            proofType: proof.proof_type || '',
            status: latestVersion?.overall_status === 'Analysis Error' ? 'error' : 'completed' as 'completed' | 'analyzing' | 'error' | 'loading',
            overallStatus: latestVersion?.overall_status as any,
            versions: proof.versions.map(v => ({
                version: v.version,
                timestamp: v.created_at.split('T')[0],
                workfrontId: v.workfront_id || '',
                proofPreviewUrl: v.thumbnail_url || '',
                feedback: v.agent_review || {} as AgentReview,
                overallStatus: v.overall_status as any,
            })),
            _id: proof.id,
        };
    }

    convertFlaggedItemToFrontend(item: FlaggedItemResponse): FlaggedItem {
        return {
            id: item.id,
            campaignName: item.campaign_name || '',
            proofName: item.proof_name || '',
            version: item.version || 1,
            submitter: item.submitter_name || '',
            submitAgency: item.submitter_agency || '',
            agentFlagged: item.agent_flagged,
            comments: item.comments || '',
            timestamp: item.created_at,
        };
    }

    convertResolvedItemToFrontend(item: ResolvedItemResponse): ResolvedItem {
        return {
            id: item.id,
            campaignName: item.campaign_name || '',
            proofName: item.proof_name || '',
            version: item.version || 1,
            submitter: item.submitter_name || '',
            submitAgency: item.submitter_agency || '',
            agent: item.agent,
            issue: item.issue || '',
            resolution: item.resolution || '',
            timestamp: item.created_at,
        };
    }

    convertErrorItemToFrontend(item: ErrorItemResponse): ErrorItem {
        return {
            id: item.id,
            campaignName: item.campaign_name || '',
            proofName: item.proof_name || '',
            version: item.version || 1,
            submitter: '',
            submitAgency: '',
            errorSummary: item.error_summary || '',
            timestamp: item.created_at,
        };
    }

    // Dropdown options endpoints
    async getDropdownOptions(): Promise<DropdownOptionsResponse> {
        return this.fetch<DropdownOptionsResponse>('/dropdown-options');
    }

    async addChannel(name: string): Promise<void> {
        await this.fetch<void>(`/dropdown-options/channels?name=${encodeURIComponent(name)}`, {
            method: 'POST',
        });
    }

    async addSubChannel(channel: string, name: string): Promise<void> {
        await this.fetch<void>(`/dropdown-options/channels/${encodeURIComponent(channel)}/sub-channels?name=${encodeURIComponent(name)}`, {
            method: 'POST',
        });
    }

    async addProofType(channel: string, subChannel: string, name: string): Promise<void> {
        await this.fetch<void>(`/dropdown-options/channels/${encodeURIComponent(channel)}/sub-channels/${encodeURIComponent(subChannel)}/proof-types?name=${encodeURIComponent(name)}`, {
            method: 'POST',
        });
    }

    async deleteChannel(channel: string): Promise<void> {
        await this.fetch<void>(`/dropdown-options/channels/${encodeURIComponent(channel)}`, {
            method: 'DELETE',
        });
    }

    async deleteSubChannel(channel: string, subChannel: string): Promise<void> {
        await this.fetch<void>(`/dropdown-options/channels/${encodeURIComponent(channel)}/sub-channels/${encodeURIComponent(subChannel)}`, {
            method: 'DELETE',
        });
    }

    async deleteProofType(channel: string, subChannel: string, proofType: string): Promise<void> {
        await this.fetch<void>(`/dropdown-options/channels/${encodeURIComponent(channel)}/sub-channels/${encodeURIComponent(subChannel)}/proof-types/${encodeURIComponent(proofType)}`, {
            method: 'DELETE',
        });
    }

    // Agency endpoints
    async getAgencies(): Promise<AgencyResponse[]> {
        return this.fetch<AgencyResponse[]>('/agencies');
    }
}

export interface DropdownOptionsResponse {
    campaigns: string[];
    channels: Record<string, Record<string, string[]>>;
    brand_guidelines: string[];
}

export interface AgencyResponse {
    id: string;
    name: string;
}

export const apiService = new ApiService();
export default apiService;
