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

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

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

// ============ 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(`/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(
          `/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(`/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(
          `/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(`/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(`/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
          ? `/skill-exam-questions?skillQuestionLibraryId=${libraryId}`
          : "/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(`/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(`/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>>(
          `/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(`/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(`/skill-exams`);
      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(`/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(`/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(`/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(`/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 (resultId: number): Promise<ResultData> => {
      try {
        const resp = await api.get(`/account/skill-exams/results/${resultId}`);
        return extract<ResultData>(resp);
      } catch (error) {
        console.error("Error fetching result:", error);
        throw error;
      }
    },
    [api],
  );

  const getResults = useCallback(async (): Promise<ResultData[]> => {
    try {
      const resp = await api.get(`/account/skill-exams/results`);
      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,
    getTest,
    createExam,
    updateExam,
    deleteExam,

    // Test Taking
    startTest,
    submitTest,

    // Results
    getResult,
    getResults,
  };
};

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

export { useSkillApi };
