import { APIRequestContext, Page } from '@playwright/test';
import { ApiBaseHelper } from '../utils/base.api';

/**
 * API Helper - Business Logic Layer
 * Tách riêng từng API: Customer → Case → Request
 */
export class ApiHelper extends ApiBaseHelper {
    constructor(page: Page, request: APIRequestContext) {
        super(page, request);
    }

    // ==================== CUSTOMER APIs ====================

    /**
     * Tạo customer mới
     * POST /api/v1/customers
     * 
     * @returns { customer_id, customerData }
     */
    async createCustomer(customerData: {
        first_name: string;
        last_name: string;
        birthday: string;
        [key: string]: any;
    }): Promise<{ customer_id: string; customerData: any }> {
        const response = await this.post('/api/v1/customers', customerData, true);

        if (response.status !== 200) {
            throw new Error(`Failed to create customer: ${response.status} - ${JSON.stringify(response.data)}`);
        }

        const customerId = response.data.data.id;

        return {
            customer_id: customerId,
            customerData: response.data.data
        };
    }

    // ==================== CONTACT MEMBER APIs ====================

    /**
     * Tạo contact member mới
     * POST /api/v1/contact-members
     * 
     * @returns { contact_id, contactData }
     */
    async createContact(contactData: {
        first_name: string;
        last_name: string;
        [key: string]: any;
    }): Promise<{ contact_id: string; contactData: any }> {
        const response = await this.post('/api/v1/contact-members', contactData, true);

        if (response.status !== 200) {
            throw new Error(`Failed to create contact: ${response.status} - ${JSON.stringify(response.data)}`);
        }

        const contactId = response.data.data.id;

        return {
            contact_id: contactId,
            contactData: response.data.data
        };
    }

    /**
     * Archive contact member
     * POST /api/v1/contact-members/{contact_id}
     * 
     * @param contactId - ID của contact cần archive
     * @returns API response
     */
    async archiveContact(contactId: string) {
        const response = await this.post(`/api/v1/contact-members/${contactId}`, {
            action: 'archived',
            _method: 'PUT'
        }, true);

        if (response.status !== 200) {
            throw new Error(`Failed to archive contact: ${response.status} - ${JSON.stringify(response.data)}`);
        }

        return response;
    }

    // ==================== CASE APIs ====================

    /**
     * Tạo case mới
     * POST /api/v1/cases
     * 
     * @returns { case_id, caseData }
     */
    async createCase(caseData: {
        customer_id: string;
        date_of_injury?: string;
        category_id: string;
        [key: string]: any;
    }): Promise<{ case_id: string; caseData: any }> {
        const response = await this.post('/api/v1/cases/create', caseData, true);

        if (response.status !== 200) {
            throw new Error(`Failed to create case: ${response.status} - ${JSON.stringify(response.data)}`);
        }

        // Response: { error: false, message: "Added New Successfully!", case_id: 138437 }
        const caseId = response.data.case_id;

        return {
            case_id: String(caseId),
            caseData: response.data
        };
    }

    // ==================== REQUEST APIs ====================

    /**
     * Tạo request mới
     * POST /api/v1/requests
     * 
     * Payload:
     * - _token (auto)
     * - message_text: '<p>message</p>'
     * - date_of_injury: '02/02/2026' (optional)
     * - intent_type: 'Awaiting'
     * - request_type_id: '10001'
     * - customer_id: 'uuid'
     * - business_provider_id: 'uuid'
     * - emails[]: ['email@test.com']
     * - send_email_notification: 1
     * - switch: 'multi'
     * 
     * @returns { request_id, requestData }
     */
    async createRequest(requestData: {
        message_text: string;
        date_of_injury?: string;
        intent_type: string;
        request_type_id: string;
        customer_id: string;
        business_provider_id?: string;
        emails?: string[];
        send_email_notification: number;
        switch: string;
        [key: string]: any;
    }): Promise<{ request_id: string; requestData: any }> {
        // Format emails array to emails[] format
        const formattedData: any = { ...requestData };
        const emails = requestData.emails || [];

        if (emails && Array.isArray(emails)) {
            delete formattedData.emails;
            emails.forEach((email, index) => {
                formattedData[`emails[${index}]`] = email;
            });
        }

        const response = await this.post('/api/v1/requests/create', formattedData, true);

        if (response.status !== 200) {
            throw new Error(`Failed to create request: ${response.status} - ${JSON.stringify(response.data)}`);
        }

        const requestId = response.data.request_id || response.data.data?.id;

        return {
            request_id: String(requestId),
            requestData: response.data
        };
    }

    // ==================== COMBINED FLOWS ====================

    /**
     * Flow: Customer → Case
     */
    async createCustomerAndCase(data: {
        first_name: string;
        last_name: string;
        birthday: string;
        date_of_injury?: string;
        category_id: string;
    }): Promise<{ customer_id: string; case_id: string; customerData: any; caseData: any }> {
        // Step 1: Create customer
        const customerResult = await this.createCustomer({
            first_name: data.first_name,
            last_name: data.last_name,
            birthday: data.birthday
        });

        // Step 2: Create case with customer_id
        const caseResult = await this.createCase({
            customer_id: customerResult.customer_id,
            date_of_injury: data.date_of_injury || "",
            category_id: data.category_id
        });

        return {
            customer_id: customerResult.customer_id,
            case_id: caseResult.case_id,
            customerData: customerResult.customerData,
            caseData: caseResult.caseData
        };
    }

    /**
     * Flow: Customer → Case → Request (Full flow)
     */
    async createFullRequest(data: {
        // Customer
        first_name: string;
        last_name: string;
        birthday: string;
        // Case
        date_of_injury?: string;
        category_id: string;
        // Request
        message_text: string;
        intent_type: string;
        request_type_id: string;
        business_provider_id?: string;
        emails?: string[];
        send_email_notification: number;
        switch: string;
    }): Promise<{
        customer_id: string;
        case_id: string;
        request_id: string;
        customerData: any;
        caseData: any;
        requestData: any;
    }> {
        // Step 1: Create customer
        const customerResult = await this.createCustomer({
            first_name: data.first_name,
            last_name: data.last_name,
            birthday: data.birthday
        });

        // Step 2: Create case
        const caseResult = await this.createCase({
            customer_id: customerResult.customer_id,
            date_of_injury: data.date_of_injury || "",
            category_id: data.category_id
        });

        // Step 3: Create request
        const requestResult = await this.createRequest({
            message_text: data.message_text,
            date_of_injury: data.date_of_injury || "",
            intent_type: data.intent_type,
            request_type_id: data.request_type_id,
            customer_id: customerResult.customer_id,
            ...(data.business_provider_id && { business_provider_id: data.business_provider_id }),
            emails: data.emails || [],
            send_email_notification: data.send_email_notification,
            switch: data.switch
        });

        return {
            customer_id: customerResult.customer_id,
            case_id: caseResult.case_id,
            request_id: String(requestResult.requestData.id),
            customerData: customerResult.customerData,
            caseData: caseResult.caseData,
            requestData: requestResult.requestData
        };
    }

    /**
     * Tạo Case → Request cho client ĐÃ TỒN TẠI
     * Dùng khi client đã có sẵn trong hệ thống (ALC_003 scenario)
     */
    async createRequestForExistingCustomer(data: {
        // Existing customer
        customer_id: string;
        // Case fields
        date_of_injury?: string;
        category_id: string;
        // Request fields
        message_text: string;
        intent_type: string;
        request_type_id: string;
        business_provider_id: string;
        emails?: string[];
        send_email_notification: number;
        switch: string;
    }): Promise<{
        case_id: string;
        request_id: string;
        caseData: any;
        requestData: any;
    }> {
        // Step 1: Create Case với existing customer
        const caseResult = await this.createCase({
            customer_id: data.customer_id,
            date_of_injury: data.date_of_injury || "",
            category_id: data.category_id
        });

        // Step 2: Create Request
        const requestResult = await this.createRequest({
            message_text: data.message_text,
            date_of_injury: data.date_of_injury || "",
            intent_type: data.intent_type,
            request_type_id: data.request_type_id,
            customer_id: data.customer_id,
            business_provider_id: data.business_provider_id,
            emails: data.emails || [],
            send_email_notification: data.send_email_notification,
            switch: data.switch
        });

        return {
            case_id: caseResult.case_id,
            request_id: String(requestResult.requestData.id),
            caseData: caseResult.caseData,
            requestData: requestResult.requestData
        };
    }

    /**
     * Tạo Request cho Case ĐÃ TỒN TẠI
     * Dùng khi cả customer và case đều đã có sẵn
     */
    async createRequestForExistingCase(data: {
        customer_id: string;
        case_id: string;
        date_of_injury?: string;
        message_text: string;
        intent_type: string;
        request_type_id: string;
        business_provider_id?: string;
        emails?: string[];
        send_email_notification: number;
        switch: string;
    }): Promise<{
        request_id: string;
        requestData: any;
    }> {
        const requestResult = await this.createRequest({
            message_text: data.message_text,
            date_of_injury: data.date_of_injury || "",
            intent_type: data.intent_type,
            request_type_id: data.request_type_id,
            customer_id: data.customer_id,
            ...(data.business_provider_id && { business_provider_id: data.business_provider_id }),
            emails: data.emails || [],
            send_email_notification: data.send_email_notification,
            switch: data.switch
        });

        return {
            request_id: String(requestResult.requestData.id),
            requestData: requestResult.requestData
        };
    }

    // ==================== OTHER APIs ====================

    async getCase(caseId: string) {
        return this.get(`/api/v1/cases/${caseId}`);
    }

    async getRequest(requestId: string) {
        return this.get(`/api/v1/requests/${requestId}`);
    }

    async archiveCase(caseId: string) {
        const response = await this.post(`/api/v1/cases/${caseId}`, {
            action: 'archive',
            _method: 'PUT'
        });

        if (response.status !== 200) {
            throw new Error(`Failed to archive case: ${response.status} - ${JSON.stringify(response.data)}`);
        }

        return response;
    }

    async archiveBusinessParticipant(caseId: string, primaryBusinessContactId: string) {
        const response = await this.post(`/api/v1/cases/${caseId}`, {
            action: 'archive-participant',
            primary_business_contact_id: primaryBusinessContactId,
            _method: 'PUT'
        });

        if (response.status !== 200) {
            throw new Error(`Failed to archive business participant: ${response.status} - ${JSON.stringify(response.data)}`);
        }

        return response;
    }

    async archiveRequest(requestId: string) {
        return this.put(`/api/v1/requests/${requestId}`, { is_archived: true });
    }

    /**
     * Move request sang case khác
     * POST /api/v1/requests/{request_id}/move
     * 
     * @param requestId - ID của request cần move
     * @param caseId - ID của case đích
     * @returns API response
     */
    async moveRequest(requestId: string, caseId: string) {
        const response = await this.post(`/api/v1/requests/${requestId}/move`, {
            case_id: caseId
        }, true);

        if (response.status !== 200) {
            throw new Error(`Failed to move request: ${response.status} - ${JSON.stringify(response.data)}`);
        }

        return response;
    }

    async changeRequestStatus(requestId: string, resolutionId: number) {
        const response = await this.post(`/api/v1/requests/${requestId}`, {
            resolution_id: resolutionId,
            _method: 'PUT'
        }, true);

        if (response.status !== 200) {
            throw new Error(`Failed to change request status: ${response.status} - ${JSON.stringify(response.data)}`);
        }

        return response;
    }

    async createBusiness(businessData: { name: string; business_type_id?: number; [key: string]: any }) {
        const response = await this.post('/api/v1/contacts', {
            business_type_id: 10001,
            ...businessData
        }, true);

        if (response.status !== 200) {
            throw new Error(`Failed to create business: ${response.status} - ${JSON.stringify(response.data)}`);
        }
    }

    async archiveCustomer(customerId: string) {
        const response = await this.post(`/api/v1/customers/${customerId}`, {
            action: 'archived',
            _method: 'PUT'
        });

        if (response.status !== 200) {
            throw new Error(`Failed to archive customer: ${response.status} - ${JSON.stringify(response.data)}`);
        }

        return response;
    }

    // ==================== BUSINESS SETTINGS APIs ====================

    /**
     * Update business setting
     * POST /api/v1/business-settings
     * 
     * @param key - Setting key (e.g., 'automation_link_case')
     * @param value - Setting value (true/false string)
     * @param expired - Expiration flag (default: 0)
     * @returns API response
     */
    async updateBusinessSetting(key: string, value: string, expired: number = 0) {
        const response = await this.post('/api/v1/business-settings', {
            key,
            value,
            expired
        }, true);

        if (response.status !== 200) {
            throw new Error(`Failed to update business setting: ${response.status} - ${JSON.stringify(response.data)}`);
        }

        return response;
    }

    /**
     * Toggle automation link case setting
     * POST /api/v1/business-settings
     * 
     * @param enable - true to enable, false to disable
     * @returns API response
     */
    async toggleAutomationLinkCase(enable: boolean) {
        return this.updateBusinessSetting('automation_link_case', String(enable), 0);
    }
}