'use client';

import { useMutation } from '@tanstack/react-query';
import { add } from 'date-fns';
import { noop } from 'lodash-es';
import { useEffect, useState } from 'react';

import Button, { ButtonSize, ButtonVariant } from '@/components/button/Button';
import {
  ContestSectionVisibility,
  dateToIsoString,
  getContestVisibilityLevel,
  isoStringToDate,
} from '@/components/contest/util';
import Link from '@/components/link/Link';
import { toast } from '@/components/toast/Toast';
import { useApiClient } from '@/lib/apiClient';
import type { components } from '@/lib/gen';

import BaseClipsSection from './editor/BaseClipsSection';
import BasicInfoSection from './editor/BasicInfoSection';
import ContestInfoSection from './editor/ContestInfoSection';
import MasterClipSection from './editor/MasterClipSection';
import TimingSection from './editor/TimingSection';
import VisibilitySection from './editor/VisibilitySection';
import WinnersPlaylistSection from './editor/WinnersPlaylistSection';

type ContestSchema = components['schemas']['ContestSchema'];
type CreateContestSpec = components['schemas']['CreateContestSpec'];
type UpdateContestSpec = components['schemas']['UpdateContestSpec'];

const DEFAULT_CONTEST_TYPE = 'remix';

interface ContestFormData {
  name: string;
  description: string;
  slug: string;
  contest_category: string;
  start_time: Date | null;
  end_time: Date | null;
  judging_start: Date | null;
  judging_end: Date | null;
  winners_announced_date: Date | null;
  contest_visibility_level: ContestSectionVisibility;
  submissions_visibility_level: ContestSectionVisibility;
  can_download_remixes: boolean;
}

/**
 * Generates default form data with current date-based defaults.
 * This function ensures dates are always computed fresh, preventing stale dates
 * when the page is loaded and a contest is created later (e.g., after midnight).
 */
function getDefaultFormData(): ContestFormData {
  const todayNoon = new Date(new Date().setHours(12, 0, 0, 0));
  return {
    name: '',
    description: '',
    slug: '',
    contest_category: '',
    start_time: todayNoon,
    end_time: add(todayNoon, { days: 6 }),
    judging_start: add(todayNoon, { days: 6 }),
    judging_end: add(todayNoon, { days: 9 }),
    winners_announced_date: add(todayNoon, { days: 9 }),
    contest_visibility_level: ContestSectionVisibility.Staff,
    submissions_visibility_level: ContestSectionVisibility.Staff,
    can_download_remixes: false,
  };
}

interface ContestEditorProps {
  contest: ContestSchema | null;
  onClose: () => void;
  onSaveSuccess: () => void;
  onDelete: (contestId: string) => void;
}

export default function ContestEditor({
  contest,
  onClose,
  onSaveSuccess,
  onDelete,
}: ContestEditorProps) {
  const apiClient = useApiClient();
  const isEditing = !!contest;
  const [isDropdownOpen, setIsDropdownOpen] = useState(false);

  const [formData, setFormData] =
    useState<ContestFormData>(getDefaultFormData());

  // Populate form when editing or clear when creating new
  useEffect(() => {
    if (contest) {
      setFormData({
        name: contest.name || '',
        description: contest.description || '',
        slug: contest.slug || '',
        contest_category: contest.contest_category || '',
        start_time: isoStringToDate(contest.start_time),
        end_time: isoStringToDate(contest.end_time),
        judging_start: isoStringToDate(contest.judging_start),
        judging_end: isoStringToDate(contest.judging_end),
        winners_announced_date: isoStringToDate(contest.winners_announced_date),
        contest_visibility_level:
          getContestVisibilityLevel(contest.contest_visibility_level) ||
          ContestSectionVisibility.Staff,
        submissions_visibility_level:
          getContestVisibilityLevel(contest.submissions_visibility_level) ||
          ContestSectionVisibility.Staff,
        can_download_remixes: contest.can_download_remixes || false,
      });
    } else {
      // Clear form for new contest
      setFormData(getDefaultFormData());
    }
  }, [contest]);

  // Create mutation
  const createMutation = useMutation({
    mutationFn: async (data: CreateContestSpec) => {
      const { data: responseData, error } = await apiClient.POST(
        '/api/contests/create_contest',
        { body: data }
      );
      if (error) throw new Error('Failed to create contest');
      return responseData;
    },
    onSuccess: () => {
      onSaveSuccess();
      toast({
        title: 'Contest created successfully!',
        status: 'success',
        duration: 2500,
        isClosable: true,
      });
    },
    onError: (error) => {
      toast({
        title: 'Failed to create contest',
        description: error instanceof Error ? error.message : undefined,
        status: 'error',
        isClosable: true,
      });
    },
  });

  // Update mutation
  const updateMutation = useMutation({
    mutationFn: async ({
      contestId,
      data,
    }: {
      contestId: string;
      data: UpdateContestSpec;
    }) => {
      const { data: responseData, error } = await apiClient.PUT(
        '/api/contests/contest/{contest_id}',
        {
          params: { path: { contest_id: contestId } },
          body: data,
        }
      );
      if (error) throw new Error('Failed to update contest');
      return responseData;
    },
    onSuccess: () => {
      onSaveSuccess();
      toast({
        title: 'Contest updated successfully!',
        status: 'success',
        duration: 2500,
        isClosable: true,
      });
    },
    onError: (error) => {
      toast({
        title: 'Failed to update contest',
        description: error instanceof Error ? error.message : undefined,
        status: 'error',
        isClosable: true,
      });
    },
  });

  const handleSubmit = (e: React.FormEvent) => {
    e.preventDefault();

    // Prepare data - convert Date objects to ISO strings for backend
    const preparedData = {
      name: formData.name,
      description: formData.description,
      type: DEFAULT_CONTEST_TYPE,
      slug: formData.slug || null,
      contest_category: formData.contest_category || null,
      start_time: dateToIsoString(formData.start_time),
      end_time: dateToIsoString(formData.end_time),
      judging_start: dateToIsoString(formData.judging_start),
      judging_end: dateToIsoString(formData.judging_end),
      winners_announced_date: dateToIsoString(formData.winners_announced_date),
      contest_visibility_level: formData.contest_visibility_level,
      submissions_visibility_level: formData.submissions_visibility_level,
      can_download_remixes: formData.can_download_remixes,
    };

    if (isEditing && contest) {
      updateMutation.mutate({
        contestId: contest.id,
        data: preparedData as UpdateContestSpec,
      });
    } else {
      createMutation.mutate(preparedData as CreateContestSpec);
    }
  };

  const updateFormData = (updates: Partial<ContestFormData>) => {
    setFormData((prev) => ({ ...prev, ...updates }));
  };

  const isLoading = createMutation.isPending || updateMutation.isPending;

  return (
    <div className='w-full p-6'>
      {/* Header */}
      <div className='mb-6 flex items-center justify-between gap-3'>
        <div className='flex items-center gap-3'>
          {/* Back button - only on mobile */}
          <Button
            onClick={onClose}
            variant={ButtonVariant.Secondary}
            size={ButtonSize.Small}
            className='md:hidden'
            aria-label='Back to contest list'
          >
            ← Back
          </Button>
          <div>
            <h2 className='text-xl font-bold text-foreground-primary md:text-2xl'>
              {isEditing ? 'Edit Contest' : 'Create New Contest'}
            </h2>
            {contest && (
              <div className='mt-1 text-xs text-foreground-secondary md:text-sm'>
                ID: {contest.id}
              </div>
            )}
          </div>
        </div>

        {/* Desktop: Show all buttons */}
        <div className='hidden items-center gap-3 md:flex'>
          {contest && (
            <Button
              href={`/collab/${contest.slug || contest.id}`}
              target='_blank'
              rel='noopener noreferrer'
              variant={ButtonVariant.Primary}
              size={ButtonSize.Small}
            >
              Visit Contest Page →
            </Button>
          )}
          {isEditing && contest && (
            <Button
              onClick={() => onDelete(contest.id)}
              variant={ButtonVariant.Secondary}
              size={ButtonSize.Small}
            >
              Delete Contest
            </Button>
          )}
        </div>

        {/* Mobile: Show dropdown menu */}
        <div className='relative md:hidden'>
          <Button
            onClick={() => setIsDropdownOpen(!isDropdownOpen)}
            variant={ButtonVariant.Secondary}
            size={ButtonSize.Small}
            aria-label='Actions menu'
          >
            ⋮
          </Button>
          {isDropdownOpen && (
            <>
              {/* Backdrop to close dropdown when clicking outside */}
              <button
                type='button'
                className='fixed inset-0 z-10'
                onClick={() => setIsDropdownOpen(false)}
                onKeyDown={(e) => {
                  if (e.key === 'Escape') setIsDropdownOpen(false);
                }}
                aria-label='Close menu'
              />
              {/* Dropdown menu */}
              <div className='absolute top-full right-0 z-20 mt-2 w-48 rounded-lg border border-border-primary bg-background-primary shadow-lg'>
                {contest && (
                  <Link
                    href={`/collab/${contest.slug || contest.id}`}
                    target='_blank'
                    rel='noopener noreferrer'
                    className='block border-b border-border-secondary px-4 py-3 text-sm font-medium text-purple-600 transition-colors hover:bg-background-secondary'
                    onClick={() => setIsDropdownOpen(false)}
                  >
                    Visit Contest Page →
                  </Link>
                )}
                {isEditing && contest && (
                  <Button
                    onClick={() => {
                      setIsDropdownOpen(false);
                      onDelete(contest.id);
                    }}
                    variant={ButtonVariant.Tertiary}
                    size={ButtonSize.Small}
                    className='w-full justify-start text-left text-red-600'
                  >
                    Delete Contest
                  </Button>
                )}
              </div>
            </>
          )}
        </div>
      </div>

      <div className='space-y-6'>
        {/* Contest Details Form - Basic Info, Timing, Visibility, Media */}
        <form onSubmit={handleSubmit}>
          <div className='rounded-lg border border-border-primary bg-background-secondary p-6'>
            <h3 className='mb-4 text-lg font-semibold text-foreground-primary'>
              Contest Details
            </h3>

            <div className='space-y-6'>
              <BasicInfoSection
                formData={formData}
                updateFormData={updateFormData}
              />

              <TimingSection
                formData={formData}
                updateFormData={updateFormData}
              />

              <VisibilitySection
                formData={formData}
                updateFormData={updateFormData}
              />
            </div>

            <div className='mt-6 border-t border-border-secondary pt-4'>
              <Button
                type='submit'
                disabled={isLoading}
                variant={ButtonVariant.Primary}
                size={ButtonSize.Large}
                onClick={noop}
              >
                {isLoading
                  ? 'Saving...'
                  : isEditing
                    ? 'Save Contest Details'
                    : 'Create Contest'}
              </Button>
            </div>
          </div>
        </form>

        {/* Base Clips Management (only for editing) */}
        {isEditing && contest && (
          <>
            <BaseClipsSection contestId={contest.id} />
            <MasterClipSection contestId={contest.id} />
            <ContestInfoSection contestId={contest.id} />
            <WinnersPlaylistSection contestId={contest.id} />
          </>
        )}
      </div>
    </div>
  );
}
