import { toast } from "sonner";
import { Job } from "./types";
import { getApiUrl, getBackofficeUrl, initConfig } from "./config";

// API Base URL - now uses runtime config
// Fetched from /api/config at runtime, falls back to build-time env or defaults

/**
 * Helper to log CRUD actions for the 'Activity Log' or console
 */
function logCrudAction(action: string, entity: string, details?: any) {
    console.log(`[CRUD] ${action.toUpperCase()} ${entity}`, details);
}

/**
 * Generic API Request Wrapper
 */
async function apiRequest<T>(endpoint: string, options: RequestInit = {}): Promise<T> {
    // Ensure config is loaded before making request
    await initConfig();

    // Token is now in httpOnly cookie, sent automatically via credentials: include
    const headers = {
        "Content-Type": "application/json",
        ...options.headers,
    };

    const response = await fetch(`${getApiUrl()}${endpoint}`, {
        ...options,
        headers,
        credentials: "include", // Enable cookie sharing
    });

    if (!response.ok) {
        const errorData = await response.json().catch(() => ({}));
        throw new Error(errorData.message || `Request failed with status ${response.status}`);
    }

    if (response.status === 204) {
        return {} as T;
    }

    return response.json();
}

// --- Types ---

export interface ApiUser {
    id: string;
    name: string;
    fullName?: string;
    email: string;
    role: "superadmin" | "admin" | "recruiter" | "candidate" | string;
    status: string;
    created_at: string;
    avatarUrl?: string;
    phone?: string;
    bio?: string;
    companyId?: string;
}

export interface ApiJob {
    id: string;
    title: string;
    companyName?: string;
    companyId: string;
    location: string;
    type: string; // "full-time", etc.
    workMode: string; // "remote", etc.
    salaryMin?: number;
    salaryMax?: number;
    salaryType?: string;
    description: string;
    requirements: string; // Backend likely returns string, frontend might expect array? Warning here.
    status: string;
    createdAt: string;
    isFeatured: boolean;
    applicationCount?: number;
}

export interface AdminCompany {
    id: string;
    name: string;
    email?: string;
    slug: string;
    type?: string;
    document?: string;
    address?: string;
    regionId?: number;
    cityId?: number;
    phone?: string;
    website?: string;
    logoUrl?: string;
    description?: string;
    active: boolean;
    verified: boolean;
    createdAt: string;  // camelCase as returned by Go json tag
    updatedAt?: string;
}

export interface AdminJob {
    id: string;
    title: string;
    companyName: string;
    status: string;
    createdAt: string;
}

export interface AdminRoleAccess {
    role: string;
    description: string;
    actions: string[];
}

export interface AdminLoginAudit {
    id: string;
    identifier: string;
    roles: string;
    ipAddress: string;
    createdAt: string;
}

export interface AdminTag {
    id: number;
    name: string;
    category: "area" | "level" | "stack";
    active: boolean;
}

export interface AdminCandidate {
    id: string;
    name: string;
    email: string;
    phone: string;
    location: string;
    title?: string;
    experience?: string;
    avatarUrl?: string;
    bio?: string;
    skills: string[];
    applications: {
        id: string;
        jobTitle: string;
        company: string;
        status: string;
    }[];
}

export interface AdminCandidateStats {
    totalCandidates: number;
    newCandidates: number;
    activeApplications: number;
    hiringRate: number;
}


// --- Auth API ---
export const authApi = {
    login: (data: any) => {
        logCrudAction("login", "auth", { email: data.email });
        return apiRequest<any>("/api/v1/auth/login", {
            method: "POST",
            body: JSON.stringify(data),
        });
    },
    register: (data: any) => {
        logCrudAction("register", "auth", { email: data.email });
        return apiRequest<any>("/api/v1/auth/register", {
            method: "POST",
            body: JSON.stringify(data),
        });
    },
    getCurrentUser: () => {
        return apiRequest<ApiUser>("/api/v1/users/me");
    },
};

// --- Users API (General/Admin) ---
// Unified to match usage in users/page.tsx
export const usersApi = {
    list: (params: { page: number; limit: number }) => {
        const query = new URLSearchParams({
            page: params.page.toString(),
            limit: params.limit.toString(),
        });
        return apiRequest<{
            data: ApiUser[];
            pagination: { total: number; page: number; limit: number };
        }>(`/api/v1/users?${query.toString()}`);
    },
    create: (data: any) => {
        logCrudAction("create", "users", data);
        return apiRequest<any>("/api/v1/users", {
            method: "POST",
            body: JSON.stringify(data),
        });
    },
    update: (id: string, data: any) => {
        logCrudAction("update", "users", { id, ...data });
        return apiRequest<any>(`/api/v1/users/${id}`, {
            method: "PATCH",
            body: JSON.stringify(data),
        });
    },
    delete: (id: string) => {
        logCrudAction("delete", "users", { id });
        return apiRequest<void>(`/api/v1/users/${id}`, {
            method: "DELETE",
        });
    },
};
export const adminUsersApi = usersApi; // Alias for backward compatibility if needed


// --- Admin Backoffice API ---
export const adminAccessApi = {
    listRoles: () => apiRequest<AdminRoleAccess[]>("/api/v1/users/roles"),
};

export const adminAuditApi = {
    listLogins: (limit = 20) => apiRequest<AdminLoginAudit[]>(`/api/v1/audit/logins?limit=${limit}`),
};

export const adminJobsApi = {
    list: (params: { status?: string; page?: number; limit?: number }) => {
        const query = new URLSearchParams();
        if (params.status) query.append("status", params.status);
        if (params.page) query.append("page", params.page.toString());
        if (params.limit) query.append("limit", params.limit.toString());

        return apiRequest<{ data: AdminJob[]; pagination: any }>(`/api/v1/jobs/moderation?${query.toString()}`);
    },
    updateStatus: (id: string, status: string) =>
        apiRequest<void>(`/api/v1/jobs/${id}/status`, {
            method: "PATCH",
            body: JSON.stringify({ status }),
        }),
    duplicate: (id: string) =>
        apiRequest<void>(`/api/v1/jobs/${id}/duplicate`, {
            method: "POST",
        }),
};

export const adminTagsApi = {
    list: (category?: string) => {
        const query = category ? `?category=${category}` : "";
        return apiRequest<AdminTag[]>(`/api/v1/tags${query}`);
    },
    create: (data: { name: string; category: string }) =>
        apiRequest<AdminTag>("/api/v1/tags", {
            method: "POST",
            body: JSON.stringify(data),
        }),
    update: (id: number, data: { name?: string; active?: boolean }) =>
        apiRequest<AdminTag>(`/api/v1/tags/${id}`, {
            method: "PATCH",
            body: JSON.stringify(data),
        }),
};

export const adminCandidatesApi = {
    list: () => apiRequest<{ candidates: AdminCandidate[]; stats: AdminCandidateStats }>("/api/v1/candidates"),
};

// --- Companies (Admin) ---
// Now handled by smart endpoint /api/v1/companies
export const adminCompaniesApi = {
    list: (verified?: boolean, page = 1, limit = 10) => {
        const query = new URLSearchParams({
            page: page.toString(),
            limit: limit.toString(),
            ...(verified !== undefined && { verified: verified.toString() })
        });
        return apiRequest<{
            data: AdminCompany[];
            pagination: {
                page: number;
                limit: number;
                total: number;
            }
        }>(`/api/v1/companies?${query.toString()}`);
    },
    create: (data: any) => {
        logCrudAction("create", "admin/companies", data);
        return apiRequest<any>("/api/v1/companies", {
            method: "POST",
            body: JSON.stringify(data),
        });
    },
    update: (id: string, data: Partial<AdminCompany>) => {
        logCrudAction("update", "admin/companies", { id, ...data });
        return apiRequest<AdminCompany>(`/api/v1/companies/${id}`, {
            method: "PATCH",
            body: JSON.stringify(data),
        });
    },
    updateStatus: (id: string, data: { active?: boolean; verified?: boolean }) => {
        logCrudAction("update", "admin/companies", { id, ...data });
        return apiRequest<void>(`/api/v1/companies/${id}/status`, {
            method: "PATCH",
            body: JSON.stringify(data),
        });
    },
    delete: (id: string) => {
        logCrudAction("delete", "admin/companies", { id });
        return apiRequest<void>(`/api/v1/companies/${id}`, {
            method: "DELETE"
        });
    }
};



// --- Jobs API (Public/Candidate) ---
export interface CreateJobPayload {
    companyId: string;
    title: string;
    description: string;
    salaryMin?: number;
    salaryMax?: number;
    salaryType?: 'hourly' | 'daily' | 'weekly' | 'monthly' | 'yearly';
    currency?: 'BRL' | 'USD' | 'EUR' | 'GBP' | 'JPY';
    salaryNegotiable?: boolean;  // When true, candidate proposes salary
    employmentType?: 'full-time' | 'part-time' | 'dispatch' | 'contract' | 'temporary' | 'training' | 'voluntary' | 'permanent';
    workingHours?: string;
    location?: string;
    status: 'draft' | 'published' | 'open';
}

export const jobsApi = {
    list: (params: {
        page?: number;
        limit?: number;
        q?: string;
        location?: string;
        type?: string;
        workMode?: string;
        companyId?: string;
        // Advanced filters
        salaryMin?: number;
        salaryMax?: number;
        currency?: string;
        visaSupport?: boolean;
        sortBy?: string;
    }) => {
        const query = new URLSearchParams();
        if (params.page) query.append("page", params.page.toString());
        if (params.limit) query.append("limit", params.limit.toString());
        if (params.q) query.append("q", params.q);
        if (params.location) query.append("location", params.location);
        if (params.type) query.append("employmentType", params.type);
        if (params.workMode) query.append("workMode", params.workMode);
        if (params.companyId) query.append("companyId", params.companyId);
        // Advanced filters
        if (params.salaryMin) query.append("salaryMin", params.salaryMin.toString());
        if (params.salaryMax) query.append("salaryMax", params.salaryMax.toString());
        if (params.currency) query.append("currency", params.currency);
        if (params.visaSupport) query.append("visaSupport", "true");
        if (params.sortBy) query.append("sortBy", params.sortBy);

        return apiRequest<{
            data: ApiJob[];
            pagination: { total: number; page: number; limit: number };
        }>(`/api/v1/jobs?${query.toString()}`);
    },
    getById: (id: string) => apiRequest<ApiJob>(`/api/v1/jobs/${id}`),
    create: (data: CreateJobPayload) => {
        logCrudAction("create", "jobs", data);
        return apiRequest<ApiJob>("/api/v1/jobs", {
            method: "POST",
            body: JSON.stringify(data),
        });
    },
    update: (id: string, data: Partial<CreateJobPayload>) => {
        logCrudAction("update", "jobs", { id, ...data });
        console.log("[JOBS_API] Updating job:", id, data);
        return apiRequest<ApiJob>(`/api/v1/jobs/${id}`, {
            method: "PUT",
            body: JSON.stringify(data),
        });
    },
    delete: (id: string) => {
        logCrudAction("delete", "jobs", { id });
        console.log("[JOBS_API] Deleting job:", id);
        return apiRequest<void>(`/api/v1/jobs/${id}`, {
            method: "DELETE",
        });
    },
};


export const applicationsApi = {
    create: (data: any) =>
        apiRequest<void>("/api/v1/applications", {
            method: "POST",
            body: JSON.stringify(data),
        }),
    list: (params: { jobId?: string; companyId?: string }) => {
        const query = new URLSearchParams();
        if (params.jobId) query.append("jobId", params.jobId);
        if (params.companyId) query.append("companyId", params.companyId);
        return apiRequest<any[]>(`/api/v1/applications?${query.toString()}`);
    },
    listMine: () => {
        return apiRequest<any[]>("/api/v1/applications/me");
    },
    delete: (id: string) => {
        return apiRequest<void>(`/api/v1/applications/${id}`, {
            method: "DELETE"
        })
    },
};

// --- Helper Functions ---
export function transformApiJobToFrontend(apiJob: ApiJob): Job {
    // Requirements might come as a string derived from DB
    let reqs: string[] = [];
    if (apiJob.requirements) {
        // Assuming it might be a JSON string or just text
        // Simple split by newline for now if it's a block of text
        reqs = apiJob.requirements.split('\n').filter(Boolean);
    }

    return {
        id: apiJob.id,
        title: apiJob.title,
        company: apiJob.companyName || "Unknown Company",
        location: apiJob.location,
        type: (apiJob.type as any) || "full-time",
        workMode: (apiJob.workMode as any) || "onsite",
        salary: apiJob.salaryMin && apiJob.salaryMax
            ? `$${apiJob.salaryMin} - $${apiJob.salaryMax}`
            : apiJob.salaryMin
                ? `$${apiJob.salaryMin}+`
                : undefined,
        description: apiJob.description,
        requirements: reqs,
        postedAt: apiJob.createdAt,
        isFeatured: apiJob.isFeatured,
    };
}


// --- Notifications ---
export interface Notification {
    id: string;
    userId: number;
    type: 'info' | 'success' | 'warning' | 'error';
    title: string;
    message: string;
    link?: string;
    readAt?: string;
    createdAt: string;
}

export const notificationsApi = {
    list: () => {
        return apiRequest<Notification[]>("/api/v1/notifications");
    },
    markAsRead: (id: string) => {
        return apiRequest<void>(`/api/v1/notifications/${id}/read`, {
            method: "PATCH",
        });
    },
    markAllAsRead: () => {
        return apiRequest<void>("/api/v1/notifications/read-all", {
            method: "PATCH",
        });
    },
};

// --- Support Tickets ---
export interface Ticket {
    id: string;
    userId: number;
    subject: string;
    status: 'open' | 'in_progress' | 'closed';
    priority: 'low' | 'medium' | 'high';
    createdAt: string;
    updatedAt: string;
}

export interface TicketMessage {
    id: string;
    ticketId: string;
    userId: number;
    message: string;
    createdAt: string;
}

export const ticketsApi = {
    create: (data: { subject: string; priority: string; message?: string }) => {
        return apiRequest<Ticket>("/api/v1/support/tickets", {
            method: "POST",
            body: JSON.stringify(data),
        });
    },
    list: () => {
        return apiRequest<Ticket[]>("/api/v1/support/tickets");
    },
    get: (id: string) => {
        return apiRequest<{ ticket: Ticket; messages: TicketMessage[] }>(`/api/v1/support/tickets/${id}`);
    },
    sendMessage: (id: string, message: string) => {
        return apiRequest<TicketMessage>(`/api/v1/support/tickets/${id}/messages`, {
            method: "POST",
            body: JSON.stringify({ message }),
        });
    },
    // Admin methods
    listAll: () => {
        return apiRequest<Ticket[]>("/api/v1/support/tickets/all");
    },
    update: (id: string, data: { status?: string; priority?: string }) => {
        return apiRequest<Ticket>(`/api/v1/support/tickets/${id}`, {
            method: "PATCH",
            body: JSON.stringify(data),
        });
    },
    delete: (id: string) => {
        return apiRequest<void>(`/api/v1/support/tickets/${id}`, {
            method: "DELETE",
        });
    },
};

// --- Profile ---
export const profileApi = {
    update: (data: { name?: string; email?: string; phone?: string; bio?: string }) => {
        return apiRequest<any>("/api/v1/users/me/profile", {
            method: "PATCH",
            body: JSON.stringify(data),
        });
    },
    updatePassword: (data: { currentPassword: string; newPassword: string }) => {
        return apiRequest<void>("/api/v1/users/me/password", {
            method: "PATCH",
            body: JSON.stringify(data),
        });
    },
    async uploadAvatar(file: File) {
        // 1. Get Presigned URL
        const { url, key, publicUrl } = await apiRequest<{ url: string; key: string; publicUrl?: string }>(
            `/api/v1/storage/upload-url?filename=${encodeURIComponent(file.name)}&contentType=${encodeURIComponent(file.type)}&folder=avatars`
        );

        // 2. Upload to S3/R2 directly
        const uploadRes = await fetch(url, {
            method: "PUT",
            headers: {
                "Content-Type": file.type,
            },
            body: file,
        });

        if (!uploadRes.ok) {
            throw new Error("Failed to upload image to storage");
        }

        // 3. Update Profile with the Key (or URL if public)
        // We save the key. The frontend or backend should resolve it to a full URL if needed.
        // For now, assuming saving the key is what's requested ("salvando as chaves").
        // We use the generic updateProfile method.
        const avatarUrl = publicUrl || key;
        console.log("[PROFILE_FLOW] Upload complete. Saving avatar URL:", avatarUrl);

        const res = await fetch(`${getApiUrl()}/api/v1/users/me/profile`, {
            method: "PATCH",
            headers: {
                "Content-Type": "application/json",
            },
            credentials: "include", // Use httpOnly cookie
            body: JSON.stringify({ avatarUrl })
        });

        if (!res.ok) throw new Error("Failed to update profile avatar");
        return res.json();
    },
};

// =============================================================================
// BACKOFFICE API (Stripe, Admin Dashboard, etc.)
// =============================================================================
// Backoffice URL - now uses runtime config

async function backofficeRequest<T>(endpoint: string, options: RequestInit = {}): Promise<T> {
    // Ensure config is loaded before making request
    await initConfig();

    // Token is now in httpOnly cookie, sent automatically via credentials: include
    const headers = {
        "Content-Type": "application/json",
        ...options.headers,
    };

    const response = await fetch(`${getBackofficeUrl()}${endpoint}`, {
        ...options,
        headers,
        credentials: "include", // Use httpOnly cookie
    });

    if (!response.ok) {
        const errorData = await response.json().catch(() => ({}));
        throw new Error(errorData.message || `Request failed with status ${response.status}`);
    }

    if (response.status === 204) {
        return {} as T;
    }

    return response.json();
}

export interface DashboardStats {
    totalCompanies: number;
    activeSubscriptions: number;
    monthlyRevenue: number;
    newCompaniesThisMonth: number;
}

export interface RevenueByMonth {
    month: string;
    revenue: number;
}

export interface SubscriptionsByPlan {
    plan: string;
    count: number;
}

export interface CheckoutSessionRequest {
    priceId: string;
    successUrl: string;
    cancelUrl: string;
}

export interface CheckoutSessionResponse {
    url: string;
    sessionId: string;
}

export const backofficeApi = {
    // Admin Dashboard
    admin: {
        getStats: () => backofficeRequest<DashboardStats>("/admin/stats"),
        getRevenue: () => backofficeRequest<RevenueByMonth[]>("/admin/revenue"),
        getSubscriptionsByPlan: () => backofficeRequest<SubscriptionsByPlan[]>("/admin/subscriptions-by-plan"),
    },
    // Stripe
    stripe: {
        createCheckoutSession: (data: CheckoutSessionRequest) =>
            backofficeRequest<CheckoutSessionResponse>("/stripe/checkout", {
                method: "POST",
                body: JSON.stringify(data),
            }),
        createBillingPortal: (returnUrl: string) =>
            backofficeRequest<{ url: string }>("/stripe/portal", {
                method: "POST",
                body: JSON.stringify({ returnUrl }),
            }),
    },
};

export const fcmApi = {
    saveToken: (token: string, platform: 'web' | 'android' | 'ios' = 'web') => {
        return apiRequest<void>("/api/v1/tokens", {
            method: "POST",
            body: JSON.stringify({ token, platform }),
        });
    },
};

// --- Chat ---
export interface Message {
    id: string;
    conversationId: string;
    senderId: string;
    content: string;
    createdAt: string;
    isMine: boolean;
}

export interface Conversation {
    id: string;
    lastMessage: string;
    lastMessageAt: string;
    participantName: string;
    participantAvatar?: string;
    unreadCount: number;
}

export const chatApi = {
    listConversations: () => apiRequest<Conversation[]>("/api/v1/conversations"),
    listMessages: (conversationId: string) => apiRequest<Message[]>(`/api/v1/conversations/${conversationId}/messages`),
    sendMessage: (conversationId: string, content: string) => apiRequest<Message>(`/api/v1/conversations/${conversationId}/messages`, {
        method: "POST",
        body: JSON.stringify({ content }),
    }),
};

export const settingsApi = {
    get: async (key: string): Promise<any> => {
        const res = await apiRequest<any>(`/api/v1/system/settings/${key}`)
        return res
    },
    save: async (key: string, value: any): Promise<void> => {
        await apiRequest<void>(`/api/v1/system/settings/${key}`, {
            method: "POST",
            body: JSON.stringify(value),
        })
    }
}

// --- System Credentials ---
export interface ConfiguredService {
    service_name: string;
    updated_at: string;
    updated_by: string;
    is_configured: boolean;
}

export const credentialsApi = {
    list: () => backofficeRequest<{ services: ConfiguredService[] }>("/system/credentials"),
    save: (serviceName: string, payload: any) => backofficeRequest<void>("/system/credentials", {
        method: "POST",
        body: JSON.stringify({ serviceName, payload }),
    }),
    delete: (serviceName: string) => backofficeRequest<void>(`/system/credentials/${serviceName}`, {
        method: "DELETE",
    }),
};

export const storageApi = {
    testConnection: () => apiRequest<{ message: string }>("/api/v1/admin/storage/test-connection", {
        method: "POST"
    }),
    async uploadFile(file: File, folder = "uploads") {
        await initConfig();
        // Use backend proxy to avoid CORS/403
        const formData = new FormData();
        formData.append('file', file);
        formData.append('folder', folder);

        // We use the proxy route
        const response = await fetch(`${getApiUrl()}/api/v1/storage/upload`, {
            method: 'POST',
            body: formData,
            // Credentials include is important if we need cookies (though for guest it might not matter, but good practice)
            credentials: 'include',
        });

        if (!response.ok) {
            const errorText = await response.text();
            throw new Error(`Failed to upload file to storage: ${errorText}`);
        }

        const data = await response.json();
        return {
            key: data.key,
            publicUrl: data.publicUrl || data.url
        };
    },
};

// --- Email Templates & Settings ---
export interface EmailTemplate {
    id: string;
    slug: string;
    subject: string;
    body_html: string;
    variables: string[];
    created_at: string;
    updated_at: string;
}

export interface EmailSettings {
    id?: string;
    provider: string;
    smtp_host?: string;
    smtp_port?: number;
    smtp_user?: string;
    smtp_pass?: string;
    smtp_secure: boolean;
    sender_name: string;
    sender_email: string;
    amqp_url?: string;
    is_active?: boolean;
    updated_at?: string;
}

export const emailTemplatesApi = {
    list: () => apiRequest<EmailTemplate[]>("/api/v1/admin/email-templates"),
    get: (slug: string) => apiRequest<EmailTemplate>(`/api/v1/admin/email-templates/${slug}`),
    create: (data: Partial<EmailTemplate>) => apiRequest<EmailTemplate>("/api/v1/admin/email-templates", {
        method: "POST",
        body: JSON.stringify(data),
    }),
    update: (slug: string, data: Partial<EmailTemplate>) => apiRequest<EmailTemplate>(`/api/v1/admin/email-templates/${slug}`, {
        method: "PUT",
        body: JSON.stringify(data),
    }),
    delete: (slug: string) => apiRequest<void>(`/api/v1/admin/email-templates/${slug}`, {
        method: "DELETE",
    }),
};

export const emailSettingsApi = {
    get: () => apiRequest<EmailSettings>("/api/v1/admin/email-settings"),
    update: (data: Partial<EmailSettings>) => apiRequest<EmailSettings>("/api/v1/admin/email-settings", {
        method: "PUT",
        body: JSON.stringify(data),
    }),
};

// --- Location API ---
export interface Country {
    id: number;
    name: string;
    iso2: string;
    iso3: string;
    phone_code: string;
    currency: string;
    emoji: string;
    emojiU: string;
}

export interface State {
    id: number;
    name: string;
    country_id: number;
    country_code: string;
    iso2: string;
    type: string;
    latitude: number;
    longitude: number;
}

export interface City {
    id: number;
    name: string;
    state_id: number;
    country_id: number;
    latitude: number;
    longitude: number;
}

export interface LocationSearchResult {
    id: number;
    name: string;
    type: 'state' | 'city';
    country_id: number;
    state_id?: number;
    region_name?: string;
}

export const locationsApi = {
    listCountries: () => apiRequest<Country[]>("/api/v1/locations/countries"),
    listStates: (countryId: number | string) => apiRequest<State[]>(`/api/v1/locations/countries/${countryId}/states`),
    listCities: (stateId: number | string) => apiRequest<City[]>(`/api/v1/locations/states/${stateId}/cities`),
    search: async (query: string, countryId: number | string) => {
        const res = await apiRequest<LocationSearchResult[]>(`/api/v1/locations/search?q=${encodeURIComponent(query)}&country_id=${countryId}`);
        return res || [];
    },
};
