import { useCallback } from "react";
import { useApiInterceptor } from "./useApiInterceptor";

type Option = {
  id?: number;
  value: string;
  [key: string]: any;
};

type Question = {
  id: number;
  title?: string;
  questionText?: string;
  description?: string;
  score?: number;
  testId?: number;
  options: Record<string, string> | Option[];
  correctAnswer?: string;
  answer?: string;
  isActive?: boolean;
  created_at?: string;
  updated_at?: string;
};

type Test = {
  id: number;
  name?: string;
  title?: string;
  passingScore?: number;
  passing_score?: number;
  questions: Question[];
  skillQuestionLibrary?: {
    questions: Question[];
  };
  description?: string;
  duration?: number;
  role?: string;
  isActive?: boolean;
};

type QuestionLibrary = {
  id: number;
  title: string;
  description?: string;
  subject?: string;
  role?: string;
  noOfQuestions?: number;
  created_at?: string;
  updated_at?: string;
};

type ExamPerformance = {
  id: number;
  candidateId: number;
  examId: number;
  examType: string;
  answerSet: Record<string, any>;
  score: string;
  status: "IN_PROGRESS" | "COMPLETED" | "NOT_STARTED";
  startTime: string;
  endTime?: string;
  created_at?: string;
  updated_at?: string;
};

type ResultData = {
  id: number;
  candidateId: number;
  examId: number;
  score: string;
  percentage?: number;
  status: string;
  startTime: string;
  endTime: string;
  answerSet: Record<string, any>;
  performance?: ExamPerformance;
  exam?: Test;
  candidate?: {
    id: number;
    user?: {
      id: number;
      name: string;
      email: string;
    };
  };
};

type CreateQuestionPayload = {
  libraryId: number;
  title: string;
  description?: string;
  options: Record<string, string> | { key: string; value: string }[];
  correctAnswer: string;
  score?: number;
  isActive?: boolean;
};

type CreateExamPayload = {
  skillQuestionLibraryId: number;
  title: string;
  description?: string;
  duration: number;
  role?: string;
  isActive?: boolean;
};

type StartExamPayload = {
  skillExamId: number;
  jobPostId?: number; // Optional: for tracking job-specific exam attempts
};

type SubmitExamPayload = {
  performanceId: number;
  answers: Record<string, string | number>;
};

type ApiResponse<T> = {
  message: string;
  data: T;
  errors?: Array<{ message: string; [key: string]: any }>;
};

// ============ LOCAL STORAGE UTILITIES ============

type StoredExamData = {
  examId: number;
  examType: "skill" | "psychometric";
  performanceId?: number;
  answers: Record<string, any>;
  timestamp: number;
  userId?: number;
};

// Local storage keys
const SKILL_EXAM_STORAGE_KEY = "skill_exam_answers";
const PSYCHOMETRIC_EXAM_STORAGE_KEY = "psychometric_exam_answers";

// Save answers to localStorage
const saveExamAnswers = (
  examId: number,
  examType: "skill" | "psychometric",
  answers: Record<string, any>,
  performanceId?: number,
  userId?: number,
) => {
  try {
    // Check if localStorage is available
    if (typeof localStorage === "undefined") {
      console.error("localStorage is not available");
      return;
    }

    const storageKey =
      examType === "skill"
        ? SKILL_EXAM_STORAGE_KEY
        : PSYCHOMETRIC_EXAM_STORAGE_KEY;
    const data: StoredExamData = {
      examId,
      examType,
      performanceId,
      answers,
      timestamp: Date.now(),
      userId,
    };
    localStorage.setItem(storageKey, JSON.stringify(data));
    console.log(`Saved ${examType} exam answers to localStorage:`, data);
    console.log(
      `Storage key: ${storageKey}, Data size:`,
      JSON.stringify(data).length,
      "characters",
    );

    // Verify it was saved
    const verify = localStorage.getItem(storageKey);
    if (verify) {
      console.log("Verified: Data was saved to localStorage");
    } else {
      console.error("Verification failed: Data was not saved to localStorage");
    }
  } catch (error) {
    console.error("Failed to save exam answers to localStorage:", error);
  }
};

// Load answers from localStorage
const loadExamAnswers = (
  examId: number,
  examType: "skill" | "psychometric",
  userId?: number,
): Record<string, any> | null => {
  try {
    const storageKey =
      examType === "skill"
        ? SKILL_EXAM_STORAGE_KEY
        : PSYCHOMETRIC_EXAM_STORAGE_KEY;
    const stored = localStorage.getItem(storageKey);

    console.log(
      `Loading ${examType} exam answers from localStorage, key: ${storageKey}, examId: ${examId}`,
    );

    if (!stored) {
      console.log(`No stored data found for key: ${storageKey}`);
      return null;
    }

    const data: StoredExamData = JSON.parse(stored);
    console.log(`Found stored data:`, data);

    // Validate data - be more flexible for migration
    if (data.examType !== examType) {
      console.log("Stored data is for different exam type, clearing...");
      clearExamAnswers(examType);
      return null;
    }

    // Allow loading if examId doesn't match (for migration between testId and examId)
    if (data.examId !== examId) {
      console.log(
        `Stored examId (${data.examId}) doesn't match requested (${examId}), but allowing for migration`,
      );
    }

    // Check if data is too old (24 hours)
    const age = Date.now() - data.timestamp;
    if (age > 24 * 60 * 60 * 1000) {
      console.log("Stored data is too old, clearing...");
      clearExamAnswers(examType);
      return null;
    }

    // Check if user matches (if provided)
    if (userId && data.userId && data.userId !== userId) {
      console.log("Stored data is for different user, clearing...");
      clearExamAnswers(examType);
      return null;
    }

    console.log(
      `Loaded ${examType} exam answers from localStorage:`,
      data.answers,
    );
    return data.answers;
  } catch (error) {
    console.error("Failed to load exam answers from localStorage:", error);
    return null;
  }
};

// Clear answers from localStorage
const clearExamAnswers = (examType: "skill" | "psychometric") => {
  try {
    const storageKey =
      examType === "skill"
        ? SKILL_EXAM_STORAGE_KEY
        : PSYCHOMETRIC_EXAM_STORAGE_KEY;
    localStorage.removeItem(storageKey);
    console.log(`Cleared ${examType} exam answers from localStorage`);
  } catch (error) {
    console.error("Failed to clear exam answers from localStorage:", error);
  }
};

// ============ HOOK IMPLEMENTATION ============
const useSkillApi = () => {
  const api = useApiInterceptor();

  // Helper to normalize response shapes: support { data: T } or { message, data: T }
  const extract = <T>(resp: any): T => {
    if (!resp) return resp;
    if (resp.data && resp.data.data !== undefined) return resp.data.data as T;
    if (resp.data !== undefined) return resp.data as T;
    return resp as T;
  };

  // --------- Question Library Methods ---------
  const getQuestionLibraries = useCallback(async (): Promise<
    QuestionLibrary[]
  > => {
    try {
      const resp = await api.get(`/account/skill-exam-question-libraries`);
      return extract<QuestionLibrary[]>(resp) || [];
    } catch (error) {
      console.error("Error fetching question libraries:", error);
      throw error;
    }
  }, [api]);

  const getQuestionLibrary = useCallback(
    async (libraryId: number): Promise<QuestionLibrary> => {
      try {
        const resp = await api.get(
          `/account/skill-exam-question-libraries/${libraryId}`,
        );
        return extract<QuestionLibrary>(resp);
      } catch (error) {
        console.error("Error fetching question library:", error);
        throw error;
      }
    },
    [api],
  );

  const createQuestionLibrary = useCallback(
    async (payload: {
      title: string;
      description?: string;
      subject?: string;
      role?: string;
      noOfQuestions?: number;
    }): Promise<QuestionLibrary> => {
      try {
        const body: any = { ...payload };
        if ((payload as any).noOfQuestions !== undefined) {
          body.noOfQuestions = (payload as any).noOfQuestions;
        }
        const resp = await api.post(
          `/account/skill-exam-question-libraries`,
          body,
        );

        const result = extract<QuestionLibrary>(resp);
        return result;
      } catch (error) {
        console.error("[API] Error creating question library:", error);
        throw error;
      }
    },
    [api],
  );

  const updateQuestionLibrary = useCallback(
    async (
      libraryId: number,
      payload: Partial<QuestionLibrary>,
    ): Promise<QuestionLibrary> => {
      try {
        const resp = await api.put(
          `/account/skill-exam-question-libraries/${libraryId}`,
          payload,
        );
        return extract<QuestionLibrary>(resp);
      } catch (error) {
        console.error("Error updating question library:", error);
        throw error;
      }
    },
    [api],
  );

  const deleteQuestionLibrary = useCallback(
    async (libraryId: number): Promise<void> => {
      try {
        await api.delete(`/account/skill-exam-question-libraries/${libraryId}`);
      } catch (error) {
        console.error("Error deleting question library:", error);
        throw error;
      }
    },
    [api],
  );

  // --------- Question Methods ---------

  // Normalize frontend payload keys (camelCase) to backend expectations
  const normalizeQuestionPayload = (payload: any) => {
    if (!payload) return payload;
    const out: any = { ...payload };

    // Convert options array to object if needed
    if (Array.isArray(payload.options)) {
      const optionsObj: Record<string, string> = {};
      payload.options.forEach((opt: any) => {
        optionsObj[opt.key] = opt.value;
      });
      out.options = optionsObj;
    }

    // Map common frontend keys to backend expected fields
    // Support payloads that use `questionText` (string) or `title`.
    if (payload.questionText) {
      out.title = payload.questionText;
    } else if (payload.title) {
      out.title = payload.title;
    }

    // Map answer -> correctAnswer (some UIs use `answer`, backend expects `correctAnswer`)
    if (payload.answer !== undefined) {
      out.correctAnswer = payload.answer;
      out.answer = payload.answer;
    } else if (payload.correctAnswer !== undefined) {
      out.correctAnswer = payload.correctAnswer;
    }

    // Support libraryId or already provided skillQuestionLibraryId
    if (payload.libraryId) {
      out.skillQuestionLibraryId = payload.libraryId;
    }

    if (payload.isActive !== undefined) {
      out.isActive = payload.isActive;
    }

    return out;
  };

  const getQuestion = useCallback(
    async (questionId: number): Promise<Question> => {
      try {
        const resp = await api.get(
          `/account/skill-exam-questions/${questionId}`,
        );
        return extract<Question>(resp);
      } catch (error) {
        console.error("Error fetching question:", error);
        throw error;
      }
    },
    [api],
  );

  const getQuestions = useCallback(
    async (libraryId?: number): Promise<Question[]> => {
      try {
        const url = libraryId
          ? `/account/skill-exam-questions?skillQuestionLibraryId=${libraryId}`
          : "/account/skill-exam-questions";
        const resp = await api.get(url);
        const data = extract<any>(resp);
        // backend may return { questions: [...] } or array directly
        if (Array.isArray(data)) return data as Question[];
        if (data?.questions) return data.questions as Question[];
        return data || [];
      } catch (error) {
        console.error("Error fetching questions:", error);
        throw error;
      }
    },
    [api],
  );

  const createQuestion = useCallback(
    async (payload: CreateQuestionPayload | any): Promise<Question> => {
      try {
        const body = normalizeQuestionPayload(payload);
        const resp = await api.post(`/account/skill-exam-questions`, body);
        return extract<Question>(resp);
      } catch (error) {
        console.error("Error creating question:", error);
        throw error;
      }
    },
    [api],
  );

  const createMultipleQuestions = useCallback(
    async (payload: CreateQuestionPayload[] | any[]): Promise<Question[]> => {
      try {
        const body = (payload || []).map((p) => normalizeQuestionPayload(p));
        const resp = await api.post(`/account/skill-exam-questions`, body);
        const data = extract<any>(resp);
        if (Array.isArray(data)) return data as Question[];
        if (data?.questions) return data.questions as Question[];
        return data || [];
      } catch (error) {
        console.error("Error creating questions:", error);
        throw error;
      }
    },
    [api],
  );

  const updateQuestion = useCallback(
    async (
      questionId: number,
      payload: Partial<CreateQuestionPayload> | any,
    ): Promise<Question> => {
      try {
        const body = normalizeQuestionPayload(payload);
        const resp = await api.put<ApiResponse<Question>>(
          `/account/skill-exam-questions/${questionId}`,
          body,
        );
        return resp.data?.data;
      } catch (error) {
        console.error("Error updating question:", error);
        throw error;
      }
    },
    [api],
  );

  const deleteQuestion = useCallback(
    async (questionId: number): Promise<void> => {
      try {
        await api.delete(`/account/skill-exam-questions/${questionId}`);
      } catch (error) {
        console.error("Error deleting question:", error);
        throw error;
      }
    },
    [api],
  );

  // --------- Exam Methods ---------

  const getExams = useCallback(async (): Promise<Test[]> => {
    try {
      const resp = await api.get(`/account/skill-exams`);
      return extract<Test[]>(resp) || [];
    } catch (error) {
      console.error("Error fetching exams:", error);
      throw error;
    }
  }, [api]);

  const getUnattachedExams = useCallback(async (): Promise<Test[]> => {
    try {
      const resp = await api.get(`/account/skill-exams`, {
        params: {
          unattachedOnly: true,
        },
      });
      return extract<Test[]>(resp) || [];
    } catch (error) {
      console.error("Error fetching exams:", error);
      throw error;
    }
  }, [api]);

  const getTest = useCallback(
    async (testId: number): Promise<Test> => {
      try {
        const resp = await api.get(`/account/skill-exams/${testId}`);
        return extract<Test>(resp);
      } catch (error) {
        console.error("Error fetching test:", error);
        throw error;
      }
    },
    [api],
  );

  const createExam = useCallback(
    async (payload: CreateExamPayload): Promise<Test> => {
      try {
        const resp = await api.post(`/account/skill-exams`, payload);
        return extract<Test>(resp);
      } catch (error) {
        console.error("Error creating exam:", error);
        throw error;
      }
    },
    [api],
  );

  const updateExam = useCallback(
    async (
      examId: number,
      payload: Partial<CreateExamPayload>,
    ): Promise<Test> => {
      try {
        const resp = await api.put(`/account/skill-exams/${examId}`, payload);
        return extract<Test>(resp);
      } catch (error) {
        console.error("Error updating exam:", error);
        throw error;
      }
    },
    [api],
  );

  const deleteExam = useCallback(
    async (examId: number): Promise<void> => {
      try {
        await api.delete(`/account/skill-exams/${examId}`);
      } catch (error) {
        console.error("Error deleting exam:", error);
        throw error;
      }
    },
    [api],
  );

  // --------- Exam Taking Methods ---------

  const startTest = useCallback(
    async (
      payload: StartExamPayload,
    ): Promise<{
      exam: Test;
      performanceId: number;
    }> => {
      try {
        const resp = await api.post(`/account/skill-exams/start`, payload);
        return extract<any>(resp);
      } catch (error) {
        console.error("Error starting test:", error);
        throw error;
      }
    },
    [api],
  );

  const submitTest = useCallback(
    async (payload: SubmitExamPayload): Promise<ResultData> => {
      try {
        const resp = await api.post(`/account/skill-exams/submit`, payload);
        return extract<ResultData>(resp);
      } catch (error) {
        console.error("Error submitting test:", error);
        throw error;
      }
    },
    [api],
  );

  // --------- Result Methods ---------

  const getResult = useCallback(
    async (performanceId: number): Promise<ResultData> => {
      try {
        const resp = await api.get(
          `/account/skill-exams/results/${performanceId}`,
        );
        return extract<ResultData>(resp);
      } catch (error) {
        console.error("Error fetching result:", error);
        throw error;
      }
    },
    [api],
  );

  const getResults = useCallback(
    async (candidateId: number): Promise<ResultData[]> => {
      try {
        console.log("candidate Id>>>", candidateId);
        const resp = await api.get(
          `/account/skill-exams/results/my-results/${candidateId}?page=1&limit=1000`,
        );
        return extract<ResultData[]>(resp) || [];
      } catch (error) {
        console.error("Error fetching results:", error);
        throw error;
      }
    },
    [api],
  );

  // Return all methods
  return {
    // Question Library (with aliases for consistency)
    getQuestionLibraries,
    getTestLibraries: getQuestionLibraries, // Alias
    getQuestionLibrary,
    getTestLibrary: getQuestionLibrary, // Alias
    createQuestionLibrary,
    createLibrary: createQuestionLibrary, // Alias
    updateQuestionLibrary,
    deleteQuestionLibrary,
    deleteLibrary: deleteQuestionLibrary, // Alias

    // Questions
    getQuestions,
    getLibraryQuestions: getQuestions, // Alias
    getQuestion,
    createQuestion,
    createMultipleQuestions,
    updateQuestion,
    deleteQuestion,

    // Exams
    getExams,
    getUnattachedExams,
    getTest,
    createExam,
    updateExam,
    deleteExam,

    // Test Taking
    startTest,
    submitTest,

    // Results
    getResult,
    getResults,

    // Local Storage Utilities
    saveExamAnswers,
    loadExamAnswers,
    clearExamAnswers,
  };
};

export type {
  Test,
  Question,
  Option,
  QuestionLibrary,
  ExamPerformance,
  ResultData,
  CreateQuestionPayload,
  CreateExamPayload,
  StartExamPayload,
  SubmitExamPayload,
  ApiResponse,
};

export { useSkillApi };
