import { toast } from "sonner";
import { Job } from "./types";

// API Base URL - endpoints already include /api/v1 prefix
// NEXT_PUBLIC_API_URL should be just the domain, e.g. https://api.gohorsejobs.com
const API_BASE_URL = process.env.NEXT_PUBLIC_API_URL || "";

/**
 * 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> {
    const token = localStorage.getItem("token");
    const headers = {
        "Content-Type": "application/json",
        ...(token ? { Authorization: `Bearer ${token}` } : {}),
        ...options.headers,
    };

    const response = await fetch(`${API_BASE_URL}${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: string;
    status: string;
    created_at: string;
    avatarUrl?: string;
    phone?: string;
    bio?: 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;
    active: boolean;
    verified: boolean;
    created_at: string;
}

export interface AdminJob {
    id: number;
    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: number;
    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: number, status: string) =>
        apiRequest<void>(`/api/v1/jobs/${id}/status`, {
            method: "PATCH",
            body: JSON.stringify({ status }),
        }),
    duplicate: (id: number) =>
        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),
        });
    },
    updateStatus: (id: number, 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: number) => {
        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';
    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;
    }) => {
        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("type", params.type);
        if (params.workMode) query.append("workMode", params.workMode);
        if (params.companyId) query.append("companyId", params.companyId);

        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),
        });
    },
};

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()}`);
    },
};

// --- 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 }),
        });
    },
};

// --- 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),
        });
    },
    uploadAvatar: async (file: File) => {
        const formData = new FormData();
        formData.append("file", file);

        // Custom fetch for multipart
        const token = localStorage.getItem("token");
        const res = await fetch(`${API_BASE_URL}/api/v1/users/me/avatar`, {
            method: "POST",
            body: formData,
            headers: {
                ...(token ? { "Authorization": `Bearer ${token}` } : {})
            }
        });
        if (!res.ok) throw new Error("Upload failed");
        return res.json();
    }
};

// =============================================================================
// BACKOFFICE API (Stripe, Admin Dashboard, etc.)
// =============================================================================
const BACKOFFICE_URL = process.env.NEXT_PUBLIC_BACKOFFICE_URL || "";

async function backofficeRequest<T>(endpoint: string, options: RequestInit = {}): Promise<T> {
    const token = localStorage.getItem("token");
    const headers = {
        "Content-Type": "application/json",
        ...(token ? { Authorization: `Bearer ${token}` } : {}),
        ...options.headers,
    };

    const response = await fetch(`${BACKOFFICE_URL}${endpoint}`, {
        ...options,
        headers,
    });

    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 }),
            }),
    },
};
