import { useEffect, useState } from "react";
import { useParams, Link, useNavigate } from "react-router";
import { ProtectedRoute } from "~/components/ProtectedRoute";
import { GradeTable } from "~/components/GradeTable";
import { GradeCalculator } from "~/components/GradeCalculator";
import { LoadingSpinner } from "~/components/LoadingSpinner";
import { Button } from "~/components/Button";
import { Input } from "~/components/Input";
import { api } from "~/api/client";
import type { Subject, Grade, GradeCreate, GradeUpdate } from "~/types/api";
import { calculateSubjectAverage, calculateTargetProgress, getTargetStatusColor } from "~/utils/gradeCalculations";
import { formatGradeBySystem, getGermanGradeDescription, germanGradeToPercentage, type GradeSystem } from "~/utils/gradeSystems";

export default function SubjectDetail() {
  const { subjectId } = useParams<{ subjectId: string }>();
  const navigate = useNavigate();
  const [subject, setSubject] = useState<Subject | null>(null);
  const [grades, setGrades] = useState<Grade[]>([]);
  const [loading, setLoading] = useState(true);
  const [showAddForm, setShowAddForm] = useState(false);
  const [editingGrade, setEditingGrade] = useState<Grade | null>(null);
  const [deletingGradeId, setDeletingGradeId] = useState<string | null>(null);

  // Form state
  const [gradeName, setGradeName] = useState("");
  const [gradeValue, setGradeValue] = useState("");
  const [maxGrade, setMaxGrade] = useState("100");
  const [category, setCategory] = useState("");
  const [weight, setWeight] = useState("1");
  const [date, setDate] = useState(new Date().toISOString().split("T")[0]);
  const [notes, setNotes] = useState("");
  const [error, setError] = useState("");

  // Get input parameters based on grading system
  const getGradeInputConfig = () => {
    const system = (subject?.grade_system || "percentage") as GradeSystem;
    switch (system) {
      case "german":
        return {
          label: "German Grade",
          placeholder: "1.0",
          min: "1",
          max: "6",
          step: "0.1",
          maxGradeValue: "6",
          showMaxGradeInput: false,
          helpText: "1 = sehr gut, 6 = ungenügend"
        };
      case "us-letter":
        return {
          label: "Percentage",
          placeholder: "85",
          min: "0",
          max: "100",
          step: "0.01",
          maxGradeValue: "100",
          showMaxGradeInput: false,
          helpText: "Enter as percentage (0-100)"
        };
      default: // percentage
        return {
          label: "Grade",
          placeholder: "85",
          min: "0",
          max: undefined,
          step: "0.01",
          maxGradeValue: "100",
          showMaxGradeInput: true,
          helpText: undefined
        };
    }
  };

  useEffect(() => {
    loadData();
  }, [subjectId]);

  const loadData = async () => {
    if (!subjectId) return;

    try {
      const [subjectData, gradesData] = await Promise.all([
        api.getSubject(subjectId),
        api.getGrades(subjectId),
      ]);
      setSubject(subjectData);
      setGrades(gradesData);
      if (subjectData.grading_categories.length > 0) {
        setCategory(subjectData.grading_categories[0].name);
      }
    } catch (error) {
      console.error("Failed to load subject:", error);
      navigate("/subjects");
    } finally {
      setLoading(false);
    }
  };

  const handleSubmitGrade = async (e: React.FormEvent) => {
    e.preventDefault();
    setError("");

    if (!subject) return;

    const config = getGradeInputConfig();
    const finalMaxGrade = config.showMaxGradeInput ? parseFloat(maxGrade) : parseFloat(config.maxGradeValue);

    try {
      if (editingGrade) {
        // Update existing grade
        const updateData: GradeUpdate = {
          category_name: category,
          grade: parseFloat(gradeValue),
          max_grade: finalMaxGrade,
          weight_in_category: parseFloat(weight),
          name: gradeName.trim() || undefined,
          date: new Date(date).toISOString(),
          notes: notes.trim() || undefined,
        };
        const updated = await api.updateGrade(editingGrade._id, updateData);
        setGrades(grades.map((g) => (g._id === editingGrade._id ? updated : g)));
      } else {
        // Create new grade
        const gradeData: GradeCreate = {
          subject_id: subject._id,
          category_name: category,
          grade: parseFloat(gradeValue),
          max_grade: finalMaxGrade,
          weight_in_category: parseFloat(weight),
          name: gradeName.trim() || undefined,
          date: new Date(date).toISOString(),
          notes: notes.trim() || undefined,
        };
        const newGrade = await api.createGrade(gradeData);
        setGrades([newGrade, ...grades]);
      }
      // Reset form
      setGradeName("");
      setGradeValue("");
      setMaxGrade("100");
      setWeight("1");
      setDate(new Date().toISOString().split("T")[0]);
      setNotes("");
      setShowAddForm(false);
      setEditingGrade(null);
    } catch (err) {
      setError(err instanceof Error ? err.message : editingGrade ? "Failed to update grade" : "Failed to add grade");
    }
  };

  const gradeInputConfig = subject ? getGradeInputConfig() : null;

  const handleEditGrade = (grade: Grade) => {
    setEditingGrade(grade);
    setGradeName(grade.name || "");
    setGradeValue(grade.grade.toString());
    setMaxGrade(grade.max_grade.toString());
    setCategory(grade.category_name);
    setWeight(grade.weight_in_category.toString());
    setDate(new Date(grade.date).toISOString().split("T")[0]);
    setNotes(grade.notes || "");
    setShowAddForm(true);
  };

  const handleCancelEdit = () => {
    setEditingGrade(null);
    setGradeName("");
    setGradeValue("");
    setMaxGrade("100");
    setWeight("1");
    setDate(new Date().toISOString().split("T")[0]);
    setNotes("");
    setShowAddForm(false);
  };

  const handleDeleteGrade = async (gradeId: string) => {
    if (!confirm("Delete this grade?")) return;

    try {
      setDeletingGradeId(gradeId);
      await api.deleteGrade(gradeId);
      setGrades(grades.filter((g) => g._id !== gradeId));
    } catch (error) {
      alert("Failed to delete grade");
    } finally {
      setDeletingGradeId(null);
    }
  };

  if (loading) {
    return (
      <ProtectedRoute>
        <div className="min-h-screen flex items-center justify-center">
          <LoadingSpinner size="lg" />
        </div>
      </ProtectedRoute>
    );
  }

  if (!subject) {
    return null;
  }

  const avgData = calculateSubjectAverage(subject, grades);
  const targetProgress = calculateTargetProgress(avgData.overallAverage, subject);

  return (
    <ProtectedRoute>
      <div className="min-h-screen bg-gray-50">
        <header className="bg-white shadow-sm border-b">
          <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
            <Link to="/subjects" className="text-blue-600 hover:text-blue-700 text-sm">
              ← Back to Subjects
            </Link>
            <div className="flex justify-between items-center mt-2">
              <div>
                <h1 className="text-2xl font-bold text-gray-900">{subject.name}</h1>
                {subject.teacher && (
                  <p className="text-sm text-gray-600">{subject.teacher}</p>
                )}
              </div>
              <div className="text-right">
                <div className="text-3xl font-bold" style={{ color: subject.color }}>
                  {avgData.overallAverage > 0 ? formatGradeBySystem(
                    avgData.overallAverage,
                    (subject.grade_system as GradeSystem) || "percentage",
                    1
                  ) : "-"}
                </div>
                <p className="text-sm text-gray-600">Overall Average</p>
                {targetProgress.status !== "no-target" && avgData.overallAverage > 0 && (
                  <div className="mt-2 pt-2 border-t">
                    <div className="flex items-center gap-2 justify-end text-sm">
                      <span className="text-gray-600">Target:</span>
                      <span className="font-semibold">
                        {formatGradeBySystem(
                          targetProgress.targetPercentage,
                          (subject.grade_system as GradeSystem) || "percentage",
                          1
                        )}
                      </span>
                    </div>
                    <div className={`text-sm font-semibold ${getTargetStatusColor(targetProgress.status)}`}>
                      {targetProgress.difference > 0 ? "+" : ""}{targetProgress.difference.toFixed(1)}% 
                      {targetProgress.status === "above" ? "above target" : targetProgress.status === "near" ? "near target" : "below target"}
                    </div>
                  </div>
                )}
              </div>
            </div>
          </div>
        </header>

        <main className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
          {/* Improvement Tip */}
          {avgData.categoryAverages.length > 1 && avgData.categoryAverages.every(c => c.average > 0) && (
            (() => {
              const sortedCategories = [...avgData.categoryAverages].sort((a, b) => a.average - b.average);
              const weakest = sortedCategories[0];
              const strongest = sortedCategories[sortedCategories.length - 1];
              const difference = strongest.average - weakest.average;
              
              if (difference > 5) { // Only show if there's a significant difference
                return (
                  <div className="bg-blue-50 border-l-4 border-blue-500 p-4 mb-6">
                    <div className="flex">
                      <div className="flex-shrink-0">
                        <svg className="h-5 w-5 text-blue-500" viewBox="0 0 20 20" fill="currentColor">
                          <path fillRule="evenodd" d="M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-7-4a1 1 0 11-2 0 1 1 0 012 0zM9 9a1 1 0 000 2v3a1 1 0 001 1h1a1 1 0 100-2v-3a1 1 0 00-1-1H9z" clipRule="evenodd" />
                        </svg>
                      </div>
                      <div className="ml-3">
                        <h3 className="text-sm font-medium text-blue-800">� Improvement Tip</h3>
                        <div className="mt-2 text-sm text-blue-700">
                          <p>
                            Your <strong>{weakest.categoryName}</strong> grades ({formatGradeBySystem(
                              weakest.average,
                              (subject.grade_system as GradeSystem) || "percentage",
                              1
                            )}) are lower than your <strong>{strongest.categoryName}</strong> ({formatGradeBySystem(
                              strongest.average,
                              (subject.grade_system as GradeSystem) || "percentage",
                              1
                            )}). 
                            Focus more on improving your {weakest.categoryName.toLowerCase()} performance to boost your overall grade!
                          </p>
                        </div>
                      </div>
                    </div>
                  </div>
                );
              }
              return null;
            })()
          )}

          {/* Grade Calculator */}
          <div className="mb-6">
            <GradeCalculator subject={subject} currentGrades={grades} />
          </div>

          {/* Category Averages */}
          <div className="grid grid-cols-1 md:grid-cols-3 gap-4 mb-8">
            {avgData.categoryAverages.map((cat) => (
              <div
                key={cat.categoryName}
                className="bg-white rounded-lg border-2 p-4"
                style={{ borderColor: cat.color || "#e5e7eb" }}
              >
                <p className="text-sm font-medium text-gray-600">{cat.categoryName}</p>
                <p className="text-2xl font-bold mt-1" style={{ color: cat.color }}>
                  {cat.average > 0 ? formatGradeBySystem(
                    cat.average,
                    (subject.grade_system as GradeSystem) || "percentage",
                    1
                  ) : "-"}
                </p>
                <p className="text-sm text-gray-500">Weight: {cat.weight}%</p>
              </div>
            ))}
          </div>

          {/* Add Grade Button/Form */}
          <div className="mb-6">
            {!showAddForm ? (
              <div className="flex gap-3">
                <Button onClick={() => setShowAddForm(true)}>+ Add Grade</Button>
                <Link to={`/subjects/${subjectId}/edit`}>
                  <Button variant="secondary">Edit Subject</Button>
                </Link>
              </div>
            ) : (
              <div className="bg-white rounded-lg shadow p-6">
                <h3 className="text-lg font-semibold mb-4">{editingGrade ? "Edit Grade" : "Add New Grade"}</h3>
                <form onSubmit={handleSubmitGrade} className="space-y-4">
                  <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
                    <Input
                      label="Grade Name (Optional)"
                      value={gradeName}
                      onChange={(e) => setGradeName(e.target.value)}
                      placeholder="e.g., Midterm Exam"
                    />
                    <div>
                      <label className="block text-sm font-medium text-gray-700 mb-1">
                        Category
                      </label>
                      <select
                        value={category}
                        onChange={(e) => setCategory(e.target.value)}
                        className="w-full px-3 py-2 border border-gray-300 rounded-lg"
                        required
                      >
                        {subject.grading_categories.map((cat) => (
                          <option key={cat.name} value={cat.name}>
                            {cat.name} ({cat.weight}%)
                          </option>
                        ))}
                      </select>
                    </div>
                    <div>
                      <Input
                        label={gradeInputConfig?.label || "Grade"}
                        type="number"
                        value={gradeValue}
                        onChange={(e) => setGradeValue(e.target.value)}
                        placeholder={gradeInputConfig?.placeholder || "85"}
                        required
                        min={gradeInputConfig?.min || "0"}
                        max={gradeInputConfig?.max}
                        step={gradeInputConfig?.step || "0.01"}
                      />
                      {gradeInputConfig?.helpText && (
                        <p className="text-xs text-gray-500 mt-1">{gradeInputConfig.helpText}</p>
                      )}
                    </div>
                    {gradeInputConfig?.showMaxGradeInput && (
                      <Input
                        label="Max Grade"
                        type="number"
                        value={maxGrade}
                        onChange={(e) => setMaxGrade(e.target.value)}
                        placeholder="100"
                        required
                        min="0"
                        step="0.01"
                      />
                    )}
                  </div>
                  
                  {/* Grade Preview */}
                  {gradeValue && gradeInputConfig && (
                    <div className="bg-blue-50 border border-blue-200 rounded-lg p-4">
                      <div className="text-sm font-medium text-blue-900 mb-1">Grade Preview</div>
                      {subject?.grade_system === "german" ? (
                        <>
                          <div className="text-2xl font-bold text-blue-700">
                            {parseFloat(gradeValue).toFixed(1)}
                          </div>
                          <div className="text-sm text-blue-600 mt-1">
                            {getGermanGradeDescription(parseFloat(gradeValue))}
                          </div>
                          <div className="text-xs text-blue-600 mt-2">
                            Percentage equivalent: {germanGradeToPercentage(parseFloat(gradeValue)).toFixed(1)}%
                          </div>
                        </>
                      ) : (
                        <>
                          <div className="text-2xl font-bold text-blue-700">
                            {formatGradeBySystem(
                              gradeInputConfig.showMaxGradeInput && maxGrade && parseFloat(maxGrade) > 0
                                ? (parseFloat(gradeValue) / parseFloat(maxGrade)) * 100
                                : parseFloat(gradeValue),
                              (subject?.grade_system as GradeSystem) || "percentage"
                            )}
                          </div>
                          {gradeInputConfig.showMaxGradeInput && maxGrade && parseFloat(maxGrade) > 0 && (
                            <div className="text-xs text-blue-600 mt-2">
                              Percentage: {((parseFloat(gradeValue) / parseFloat(maxGrade)) * 100).toFixed(1)}%
                            </div>
                          )}
                        </>
                      )}
                    </div>
                  )}

                  <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
                    <Input
                      label="Weight in Category"
                      type="number"
                      value={weight}
                      onChange={(e) => setWeight(e.target.value)}
                      placeholder="1"
                      required
                      min="0"
                      step="0.1"
                    />
                    <Input
                      label="Date"
                      type="date"
                      value={date}
                      onChange={(e) => setDate(e.target.value)}
                      required
                    />
                  </div>
                  <Input
                    label="Notes (Optional)"
                    value={notes}
                    onChange={(e) => setNotes(e.target.value)}
                    placeholder="Additional notes..."
                  />
                  {error && (
                    <div className="bg-red-50 border border-red-200 text-red-700 px-4 py-3 rounded">
                      {error}
                    </div>
                  )}
                  <div className="flex gap-3">
                    <Button type="submit">{editingGrade ? "Update Grade" : "Add Grade"}</Button>
                    <Button
                      type="button"
                      variant="secondary"
                      onClick={handleCancelEdit}
                    >
                      Cancel
                    </Button>
                  </div>
                </form>
              </div>
            )}
          </div>

          {/* Grades Table */}
          <div className="bg-white rounded-lg shadow p-6">
            <h3 className="text-lg font-semibold mb-4">All Grades</h3>
            <GradeTable
              grades={grades}
              subject={subject}
              onEdit={handleEditGrade}
              onDelete={handleDeleteGrade}
              deletingGradeId={deletingGradeId}
            />
          </div>
        </main>
      </div>
    </ProtectedRoute>
  );
}
