import React, { useEffect, useMemo, useState } from 'react';
import type { Session } from '@supabase/supabase-js';

import Loader from './Loader';
import { isSupabaseConfigured, supabase } from '../services/supabaseClient';

interface FipiTask {
  id: number;
  title: string;
  content: string;
  task_type: string | null;
  source_url: string;
  scraped_at: string;
  variants?: string[];
  can_check_answer?: boolean;
}

interface TaskAttempt {
  id?: number;
  task_id: number;
  submitted_answer: string;
  is_correct: boolean;
  check_status: string;
  created_at: string;
}

interface CheckAnswerResult {
  success: boolean;
  is_correct: boolean;
  status_code: string;
  status_label: string;
  submitted_answer: string;
  normalized_answer: string;
  message: string;
}

interface TasksTabProps {
  session: Session | null;
  scraperUrl?: string;
}

const FILTERS = ['all', 'checkable', 'writing', 'test', 'reading', 'listening', 'other'] as const;

const sourceLabel = (task: FipiTask) => {
  if (task.source_url.includes('questions.php')) return 'Банк ФИПИ';
  if (task.source_url.includes('otkrytyye-varianty-kim-ege')) return 'Открытый вариант';
  if (task.source_url.includes('demoversii-specifikacii-kodifikatory')) return 'Демоверсия';
  return 'Источник ФИПИ';
};

const TasksTab: React.FC<TasksTabProps> = ({
  session,
  scraperUrl = import.meta.env.VITE_SCRAPER_URL || 'http://localhost:8000',
}) => {
  const [tasks, setTasks] = useState<FipiTask[]>([]);
  const [attempts, setAttempts] = useState<TaskAttempt[]>([]);
  const [localAttempts, setLocalAttempts] = useState<TaskAttempt[]>([]);
  const [answerDrafts, setAnswerDrafts] = useState<Record<number, string>>({});
  const [checkResults, setCheckResults] = useState<Record<number, CheckAnswerResult>>({});
  const [selectedTaskId, setSelectedTaskId] = useState<number | null>(null);
  const [filterType, setFilterType] = useState<(typeof FILTERS)[number]>('checkable');
  const [search, setSearch] = useState('');
  const [loading, setLoading] = useState(true);
  const [statsLoading, setStatsLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [checkingTaskId, setCheckingTaskId] = useState<number | null>(null);

  const fetchTasks = async () => {
    setLoading(true);
    setError(null);
    try {
      const response = await fetch(`${scraperUrl}/api/tasks`);
      if (!response.ok) {
        throw new Error('Не удалось загрузить задания.');
      }
      const data = await response.json();
      const taskList = (Array.isArray(data) ? data : data.tasks || []) as FipiTask[];
      setTasks(taskList);
    } catch (err) {
      setError(err instanceof Error ? err.message : 'Не удалось загрузить задания.');
    } finally {
      setLoading(false);
    }
  };

  const fetchAttempts = async () => {
    if (!session || !isSupabaseConfigured()) {
      setAttempts([]);
      return;
    }

    setStatsLoading(true);
    try {
      const { data, error: selectError } = await supabase
        .from('task_attempts')
        .select('*')
        .eq('user_id', session.user.id)
        .order('created_at', { ascending: false });

      if (selectError) {
        throw selectError;
      }
      setAttempts((data || []) as TaskAttempt[]);
    } catch {
      setAttempts([]);
    } finally {
      setStatsLoading(false);
    }
  };

  useEffect(() => {
    fetchTasks();
  }, [scraperUrl]);

  useEffect(() => {
    fetchAttempts();
  }, [session]);

  const allAttempts = session ? attempts : localAttempts;

  const latestAttemptByTask = useMemo(() => {
    const latest = new Map<number, TaskAttempt>();
    for (const attempt of allAttempts) {
      if (!latest.has(attempt.task_id)) {
        latest.set(attempt.task_id, attempt);
      }
    }
    return latest;
  }, [allAttempts]);

  const taskStats = useMemo(() => {
    const totalAttempts = allAttempts.length;
    const incorrectAttempts = allAttempts.filter((attempt) => !attempt.is_correct).length;
    const correctAttempts = totalAttempts - incorrectAttempts;
    const solvedTasks = new Set(allAttempts.filter((attempt) => attempt.is_correct).map((attempt) => attempt.task_id)).size;
    const accuracy = totalAttempts === 0 ? 0 : Math.round((correctAttempts / totalAttempts) * 100);

    const wrongByTask = new Map<number, number>();
    for (const attempt of allAttempts) {
      if (!attempt.is_correct) {
        wrongByTask.set(attempt.task_id, (wrongByTask.get(attempt.task_id) || 0) + 1);
      }
    }

    const hardestTasks = Array.from(wrongByTask.entries())
      .sort((left, right) => right[1] - left[1])
      .slice(0, 5)
      .map(([taskId, wrongCount]) => ({
        task: tasks.find((task) => task.id === taskId),
        wrongCount,
      }))
      .filter((item) => item.task);

    return {
      totalAttempts,
      incorrectAttempts,
      correctAttempts,
      solvedTasks,
      accuracy,
      hardestTasks,
    };
  }, [allAttempts, tasks]);

  const filteredTasks = useMemo(() => {
    const normalizedQuery = search.trim().toLowerCase();
    return tasks
      .filter((task) => {
        if (filterType === 'checkable') {
          return Boolean(task.can_check_answer);
        }
        if (filterType !== 'all') {
          return task.task_type === filterType;
        }
        return true;
      })
      .filter((task) => {
        if (!normalizedQuery) {
          return true;
        }
        return (
          task.title.toLowerCase().includes(normalizedQuery) ||
          task.content.toLowerCase().includes(normalizedQuery)
        );
      })
      .sort((left, right) => Number(Boolean(right.can_check_answer)) - Number(Boolean(left.can_check_answer)));
  }, [filterType, search, tasks]);

  const submitAnswer = async (task: FipiTask) => {
    const draft = (answerDrafts[task.id] || '').trim();
    if (!draft) {
      setCheckResults((current) => ({
        ...current,
        [task.id]: {
          success: false,
          is_correct: false,
          status_code: 'validation_error',
          status_label: 'Пустой ответ',
          submitted_answer: draft,
          normalized_answer: '',
          message: 'Введите ответ перед проверкой.',
        },
      }));
      return;
    }

    setCheckingTaskId(task.id);
    try {
      const response = await fetch(`${scraperUrl}/api/tasks/${task.id}/check-answer`, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ answer: draft }),
      });
      const payload = (await response.json()) as CheckAnswerResult | { detail?: string };
      if (!response.ok) {
        throw new Error('detail' in payload && payload.detail ? payload.detail : 'Проверка не удалась.');
      }

      const result = payload as CheckAnswerResult;
      setCheckResults((current) => ({ ...current, [task.id]: result }));

      const attempt: TaskAttempt = {
        task_id: task.id,
        submitted_answer: draft,
        is_correct: result.is_correct,
        check_status: result.status_code,
        created_at: new Date().toISOString(),
      };

      if (session && isSupabaseConfigured()) {
        const { error: insertError } = await supabase.from('task_attempts').insert({
          user_id: session.user.id,
          task_id: task.id,
          submitted_answer: draft,
          is_correct: result.is_correct,
          check_status: result.status_code,
        });

        if (!insertError) {
          await fetchAttempts();
        }
      } else {
        setLocalAttempts((current) => [attempt, ...current]);
      }
    } catch (err) {
      setCheckResults((current) => ({
        ...current,
        [task.id]: {
          success: false,
          is_correct: false,
          status_code: 'request_error',
          status_label: 'Ошибка',
          submitted_answer: draft,
          normalized_answer: draft,
          message: err instanceof Error ? err.message : 'Проверка не удалась.',
        },
      }));
    } finally {
      setCheckingTaskId(null);
    }
  };

  if (loading) {
    return (
      <div className="flex justify-center py-20">
        <Loader />
      </div>
    );
  }

  return (
    <div className="mx-auto max-w-6xl space-y-6 pb-12 animate-fade-in">
      <div className="rounded-2xl border border-stone-200 bg-white p-6 shadow-sm">
        <div className="flex flex-col gap-4 lg:flex-row lg:items-end lg:justify-between">
          <div>
            <h2 className="text-3xl font-serif font-bold text-refined-dark">Практика по заданиям ФИПИ</h2>
            <p className="mt-1 text-stone-500">
              Задания подгружаются из базы автоматически. Проверка ответа доступна для задач из банка ФИПИ.
            </p>
          </div>
          <div className="flex flex-col gap-3 sm:flex-row">
            <input
              value={search}
              onChange={(event) => setSearch(event.target.value)}
              placeholder="Поиск по тексту задания"
              className="rounded-full border border-stone-300 px-4 py-3 text-sm text-stone-700 outline-none transition focus:border-refined-red"
            />
            <button
              onClick={fetchTasks}
              className="rounded-full bg-stone-100 px-5 py-3 text-sm font-medium text-stone-700 transition hover:bg-stone-200"
            >
              Обновить список
            </button>
          </div>
        </div>

        <div className="mt-5 flex flex-wrap gap-2">
          {FILTERS.map((filter) => {
            const count =
              filter === 'all'
                ? tasks.length
                : filter === 'checkable'
                  ? tasks.filter((task) => task.can_check_answer).length
                  : tasks.filter((task) => task.task_type === filter).length;
            if (count === 0 && filter !== 'all') {
              return null;
            }
            return (
              <button
                key={filter}
                onClick={() => setFilterType(filter)}
                className={`rounded-full px-4 py-2 text-sm font-medium transition ${
                  filterType === filter
                    ? 'bg-refined-red text-white'
                    : 'bg-stone-100 text-stone-600 hover:bg-stone-200'
                }`}
              >
                {filter === 'all' ? 'Все' : filter === 'checkable' ? 'С проверкой' : filter}
                {' '}
                ({count})
              </button>
            );
          })}
        </div>
      </div>

      <div className="grid gap-4 md:grid-cols-4">
        <div className="rounded-2xl border border-stone-200 bg-white p-5 shadow-sm">
          <p className="text-xs font-bold uppercase text-stone-500">Всего заданий</p>
          <p className="mt-2 text-3xl font-serif font-bold text-refined-dark">{tasks.length}</p>
        </div>
        <div className="rounded-2xl border border-stone-200 bg-white p-5 shadow-sm">
          <p className="text-xs font-bold uppercase text-stone-500">Решено</p>
          <p className="mt-2 text-3xl font-serif font-bold text-refined-dark">{taskStats.solvedTasks}</p>
        </div>
        <div className="rounded-2xl border border-stone-200 bg-white p-5 shadow-sm">
          <p className="text-xs font-bold uppercase text-stone-500">Ошибок</p>
          <p className="mt-2 text-3xl font-serif font-bold text-refined-dark">{taskStats.incorrectAttempts}</p>
        </div>
        <div className="rounded-2xl border border-stone-200 bg-white p-5 shadow-sm">
          <p className="text-xs font-bold uppercase text-stone-500">Точность</p>
          <p className="mt-2 text-3xl font-serif font-bold text-refined-dark">{taskStats.accuracy}%</p>
        </div>
      </div>

      {(statsLoading || taskStats.hardestTasks.length > 0) && (
        <div className="rounded-2xl border border-stone-200 bg-white p-6 shadow-sm">
          <h3 className="font-serif text-xl font-bold text-refined-dark">Статистика ошибок</h3>
          {statsLoading ? (
            <div className="mt-4 flex justify-center">
              <Loader />
            </div>
          ) : taskStats.hardestTasks.length === 0 ? (
            <p className="mt-3 text-stone-500">Пока нет ошибок по сохранённым попыткам.</p>
          ) : (
            <div className="mt-4 space-y-3">
              {taskStats.hardestTasks.map(({ task, wrongCount }) => (
                <div key={task!.id} className="rounded-xl border border-stone-200 bg-stone-50 p-4">
                  <div className="flex items-start justify-between gap-4">
                    <div>
                      <p className="font-semibold text-refined-dark">{task!.title}</p>
                      <p className="mt-1 text-sm text-stone-500">{sourceLabel(task!)}</p>
                    </div>
                    <span className="rounded-full bg-red-100 px-3 py-1 text-xs font-medium text-red-700">
                      Ошибок: {wrongCount}
                    </span>
                  </div>
                </div>
              ))}
            </div>
          )}
        </div>
      )}

      {error && (
        <div className="rounded-2xl border border-red-200 bg-red-50 p-6 text-red-700">
          {error}
        </div>
      )}

      <div className="space-y-4">
        {filteredTasks.map((task) => {
          const latestAttempt = latestAttemptByTask.get(task.id);
          const isExpanded = selectedTaskId === task.id;
          const checkResult = checkResults[task.id];
          return (
            <div key={task.id} className="rounded-2xl border border-stone-200 bg-white shadow-sm">
              <div className="flex flex-col gap-4 p-6 md:flex-row md:items-start md:justify-between">
                <div className="min-w-0 flex-1">
                  <div className="flex flex-wrap items-center gap-2">
                    <span className="rounded-full bg-stone-100 px-3 py-1 text-xs font-medium text-stone-600">
                      {sourceLabel(task)}
                    </span>
                    {task.can_check_answer && (
                      <span className="rounded-full bg-emerald-100 px-3 py-1 text-xs font-medium text-emerald-700">
                        Можно проверить
                      </span>
                    )}
                    {latestAttempt && (
                      <span
                        className={`rounded-full px-3 py-1 text-xs font-medium ${
                          latestAttempt.is_correct
                            ? 'bg-emerald-100 text-emerald-700'
                            : 'bg-red-100 text-red-700'
                        }`}
                      >
                        {latestAttempt.is_correct ? 'Последний ответ верный' : 'Последний ответ неверный'}
                      </span>
                    )}
                  </div>
                  <h3 className="mt-3 text-xl font-semibold text-refined-dark">{task.title}</h3>
                  <p className="mt-2 line-clamp-3 whitespace-pre-wrap text-sm text-stone-600">{task.content}</p>
                </div>
                <button
                  onClick={() => setSelectedTaskId(isExpanded ? null : task.id)}
                  className="rounded-full bg-stone-100 px-4 py-2 text-sm font-medium text-stone-700 transition hover:bg-stone-200"
                >
                  {isExpanded ? 'Скрыть' : 'Открыть'}
                </button>
              </div>

              {isExpanded && (
                <div className="border-t border-stone-200 px-6 py-6">
                  <div className="rounded-xl border border-stone-200 bg-refined-paper p-5">
                    <p className="whitespace-pre-wrap text-stone-700">{task.content}</p>

                    {task.variants && task.variants.length > 0 && (
                      <div className="mt-5">
                        <p className="mb-2 text-sm font-semibold text-refined-dark">Варианты из задания</p>
                        <div className="space-y-2">
                          {task.variants.map((variant, index) => (
                            <div key={`${task.id}-variant-${index}`} className="rounded-lg bg-white px-3 py-2 text-sm text-stone-700">
                              {variant}
                            </div>
                          ))}
                        </div>
                      </div>
                    )}

                    <div className="mt-6 space-y-3">
                      {task.can_check_answer ? (
                        <>
                          <label className="block text-sm font-semibold text-refined-dark">
                            Введите ответ
                          </label>
                          <div className="flex flex-col gap-3 md:flex-row">
                            <input
                              value={answerDrafts[task.id] || ''}
                              onChange={(event) =>
                                setAnswerDrafts((current) => ({
                                  ...current,
                                  [task.id]: event.target.value,
                                }))
                              }
                              placeholder="Например: 25 или СЛОВО"
                              className="flex-1 rounded-xl border border-stone-300 px-4 py-3 text-sm text-stone-700 outline-none transition focus:border-refined-red"
                            />
                            <button
                              onClick={() => submitAnswer(task)}
                              disabled={checkingTaskId === task.id}
                              className="rounded-xl bg-refined-red px-5 py-3 text-sm font-medium text-white transition hover:bg-red-700 disabled:cursor-not-allowed disabled:opacity-60"
                            >
                              {checkingTaskId === task.id ? 'Проверяю...' : 'Проверить'}
                            </button>
                          </div>
                          <p className="text-xs text-stone-500">
                            Для статистики попытки сохраняются в Supabase, если пользователь авторизован.
                          </p>
                        </>
                      ) : (
                        <div className="rounded-xl border border-amber-200 bg-amber-50 p-4 text-sm text-amber-800">
                          Для этой задачи автоматическая проверка пока недоступна. Проверка работает для задач из динамического банка ФИПИ.
                        </div>
                      )}

                      {checkResult && (
                        <div
                          className={`rounded-xl p-4 text-sm font-medium ${
                            checkResult.is_correct
                              ? 'bg-emerald-50 text-emerald-700'
                              : 'bg-red-50 text-red-700'
                          }`}
                        >
                          <p>{checkResult.message}</p>
                          <p className="mt-1 text-xs opacity-80">
                            Отправлено: {checkResult.submitted_answer}
                          </p>
                        </div>
                      )}
                    </div>

                    <a
                      href={task.source_url}
                      target="_blank"
                      rel="noopener noreferrer"
                      className="mt-5 inline-flex items-center gap-2 text-sm font-medium text-refined-red hover:underline"
                    >
                      Открыть источник
                    </a>
                  </div>
                </div>
              )}
            </div>
          );
        })}
      </div>

      {!error && filteredTasks.length === 0 && (
        <div className="rounded-2xl border border-stone-200 bg-white p-10 text-center text-stone-500 shadow-sm">
          По текущему фильтру заданий не найдено.
        </div>
      )}
    </div>
  );
};

export default TasksTab;
