import { useState, useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import { TZDate } from 'react-day-picker';
import {
  Dialog,
  DialogContent,
  DialogHeader,
  DialogTitle,
} from '@/components/ui/dialog';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover';
import { Calendar } from '@/components/ui/calendar';
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from '@/components/ui/select';
import { Folder, ArrowUp, ArrowRight, ArrowDown, Circle, Clock, CheckCircle2, Calendar as CalIcon, UserPlus, Plus, Paperclip } from 'lucide-react';
import { trpc } from '@/lib/trpc';
import { PropertyPill } from './PropertyPill';
import { InlineProjectForm } from './InlineProjectForm';
import { useFormatPrefs, formatDueDate } from '@/lib/date';
import { useTaskAttachments } from './useTaskAttachments';

const HOURS = Array.from({ length: 24 }, (_, i) => String(i).padStart(2, '0'));
const MINUTES = ['00', '05', '10', '15', '20', '25', '30', '35', '40', '45', '50', '55'];

/**
 * Decode a ms-epoch timestamp into Y/M/D H/M parts as observed in the given IANA timezone.
 * Returns null when ms is null/undefined.
 */
function derivePartsInTz(
  ms: number | null | undefined,
  timezone: string,
): { year: number; month: number; day: number; hour: number; minute: number } | null {
  if (ms == null) return null;
  const fmt = new Intl.DateTimeFormat('en-CA', {
    timeZone: timezone,
    year: 'numeric',
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit',
    hour12: false,
  });
  const parts = fmt.formatToParts(new Date(ms));
  const get = (type: string) => parseInt(parts.find((p) => p.type === type)?.value ?? '0', 10);
  return {
    year: get('year'),
    month: get('month'),
    day: get('day'),
    // 24h Intl formatters in some locales render midnight as "24" — normalize to 0.
    hour: get('hour') % 24,
    minute: get('minute'),
  };
}

export type TaskFormValues = {
  title: string;
  description: string;
  priority: string;
  status: string;
  dueDate: number | null;
  projectId: string | null;
  assignees: string[];
  estimate: number | null;
};

interface Props {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  mode: 'create' | 'edit';
  taskId?: string;
  initialValues?: Partial<TaskFormValues>;
  onSubmit: (values: TaskFormValues) => void;
  isSubmitting?: boolean;
}

const DEFAULTS: TaskFormValues = {
  title: '',
  description: '',
  priority: 'medium',
  status: 'todo',
  dueDate: null,
  projectId: null,
  assignees: [],
  estimate: null,
};

export function TaskFormDialog({
  open,
  onOpenChange,
  mode,
  taskId,
  initialValues,
  onSubmit,
  isSubmitting,
}: Props) {
  const { t } = useTranslation();
  const [values, setValues] = useState<TaskFormValues>({ ...DEFAULTS, ...initialValues });
  const [projectPopoverOpen, setProjectPopoverOpen] = useState(false);
  const [creatingProject, setCreatingProject] = useState(false);
  const [assigneeInput, setAssigneeInput] = useState('');

  useEffect(() => {
    if (open) {
      setValues({ ...DEFAULTS, ...initialValues });
      setCreatingProject(false);
      setAssigneeInput('');
      setProjectPopoverOpen(false);
    }
  }, [open, initialValues]);

  function addNewAssignee() {
    const name = assigneeInput.trim();
    if (!name) return;
    setValues((v) => (v.assignees.includes(name) ? v : { ...v, assignees: [...v.assignees, name] }));
    setAssigneeInput('');
  }

  const { data: projectsList = [] } = trpc.projects.listAll.useQuery();
  const { data: knownAssignees = [] } = trpc.tasks.listAssignees.useQuery();
  const prefs = useFormatPrefs();
  const selectedProject = projectsList.find((p) => p.id === values.projectId);
  const attachments = useTaskAttachments(mode === 'edit' && taskId ? taskId : null);

  // Derive H/M from current dueDate in user timezone for display in time selects.
  const parts = derivePartsInTz(values.dueDate, prefs.timezone);
  const dueHour = parts ? String(parts.hour).padStart(2, '0') : '';
  // Snap minute display to nearest 5-minute step value if in selectable list.
  const minuteStr = parts ? String(parts.minute).padStart(2, '0') : '';
  const dueMinute = MINUTES.includes(minuteStr) ? minuteStr : '';

  function updateDueTime(hour: string, minute: string) {
    if (!values.dueDate) return;
    const cur = derivePartsInTz(values.dueDate, prefs.timezone);
    if (!cur) return;
    const tz = new TZDate(
      cur.year,
      cur.month - 1,
      cur.day,
      parseInt(hour, 10),
      parseInt(minute, 10),
      0,
      0,
      prefs.timezone,
    );
    setValues((v) => ({ ...v, dueDate: tz.getTime() }));
  }

  function handleSubmit(e: React.FormEvent) {
    e.preventDefault();
    if (!values.title.trim()) return;
    onSubmit({ ...values, title: values.title.trim() });
  }

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="sm:max-w-[580px] p-0 gap-0 overflow-hidden bg-card/92 backdrop-blur-xl">
        <DialogHeader className="px-5 py-3 border-b border-border/40">
          <DialogTitle className="text-sm font-medium">
            {mode === 'create' ? t('tasks.newTask') : t('tasks.editTask')}
          </DialogTitle>
        </DialogHeader>

        <form
          onSubmit={handleSubmit}
          onKeyDown={(e) => {
            if ((e.metaKey || e.ctrlKey) && e.key === 'Enter') handleSubmit(e);
          }}
        >
          <div className="px-5 pt-5 pb-2">
            <input
              autoFocus
              className="w-full bg-transparent border-none outline-none text-[22px] font-medium leading-tight placeholder:text-muted-foreground/60"
              placeholder={t('tasks.whatNeedsToBeDone')}
              value={values.title}
              onChange={(e) => setValues((v) => ({ ...v, title: e.target.value }))}
            />
            <textarea
              className="mt-2 w-full bg-transparent border-none outline-none text-sm resize-none placeholder:text-muted-foreground/60"
              rows={3}
              placeholder={t('tasks.descriptionOptional')}
              value={values.description}
              onChange={(e) => setValues((v) => ({ ...v, description: e.target.value }))}
            />
          </div>

          {/* PROPERTIES section + footer go in next tasks */}
          <div className="px-5 pb-3 pt-1">
            <div className="text-[10px] uppercase tracking-wider text-muted-foreground mb-2">
              {t('tasks.properties')}
            </div>
            <div className="flex flex-wrap gap-1.5" data-testid="property-pills">
              {/* Project */}
              <Popover
                open={projectPopoverOpen}
                onOpenChange={(o) => {
                  setProjectPopoverOpen(o);
                  if (!o) setCreatingProject(false);
                }}
              >
                <PopoverTrigger asChild>
                  <span>
                    <PropertyPill
                      icon={<Folder className="h-3 w-3" />}
                      label={t('tasks.project')}
                      value={selectedProject?.name ?? null}
                      empty={!selectedProject}
                    />
                  </span>
                </PopoverTrigger>
                <PopoverContent className="w-72 p-0 max-h-96 overflow-y-auto" align="start">
                  {creatingProject ? (
                    <InlineProjectForm
                      onCancel={() => setCreatingProject(false)}
                      onCreated={(id) => {
                        setValues((v) => ({ ...v, projectId: id }));
                        setCreatingProject(false);
                        setProjectPopoverOpen(false);
                      }}
                    />
                  ) : (
                    <div className="p-1">
                      <button
                        type="button"
                        className="w-full text-left px-2 py-1.5 text-sm rounded hover:bg-accent/50 flex items-center gap-1.5 text-primary"
                        onClick={() => setCreatingProject(true)}
                      >
                        <Plus className="h-3.5 w-3.5" />
                        {t('projects.newProject')}
                      </button>
                      <div className="my-1 h-px bg-border/60" />
                      <button
                        type="button"
                        className="w-full text-left px-2 py-1.5 text-sm rounded hover:bg-accent/50"
                        onClick={() => {
                          setValues((v) => ({ ...v, projectId: null }));
                          setProjectPopoverOpen(false);
                        }}
                      >
                        {t('tasks.noProject')}
                      </button>
                      {projectsList.map((p) => (
                        <button
                          key={p.id}
                          type="button"
                          className="w-full text-left px-2 py-1.5 text-sm rounded hover:bg-accent/50"
                          onClick={() => {
                            setValues((v) => ({ ...v, projectId: p.id }));
                            setProjectPopoverOpen(false);
                          }}
                        >
                          {p.name}
                        </button>
                      ))}
                    </div>
                  )}
                </PopoverContent>
              </Popover>

              {/* Priority */}
              <Popover>
                <PopoverTrigger asChild>
                  <span>
                    <PropertyPill
                      icon={
                        values.priority === 'high' ? <ArrowUp className="h-3 w-3 text-red-600" /> :
                        values.priority === 'low' ? <ArrowDown className="h-3 w-3 text-muted-foreground" /> :
                        <ArrowRight className="h-3 w-3 text-amber-600" />
                      }
                      label={t('tasks.priority')}
                      value={t(`tasks.${values.priority}`)}
                    />
                  </span>
                </PopoverTrigger>
                <PopoverContent className="w-40 p-1" align="start">
                  {(['high', 'medium', 'low'] as const).map((p) => (
                    <button
                      key={p}
                      type="button"
                      onClick={() => setValues((v) => ({ ...v, priority: p }))}
                      className="w-full text-left px-2 py-1.5 text-sm rounded hover:bg-accent/50"
                    >
                      {t(`tasks.${p}`)}
                    </button>
                  ))}
                </PopoverContent>
              </Popover>

              {/* Status */}
              <Popover>
                <PopoverTrigger asChild>
                  <span>
                    <PropertyPill
                      icon={
                        values.status === 'in_progress' ? <Clock className="h-3 w-3" /> :
                        values.status === 'done' ? <CheckCircle2 className="h-3 w-3" /> :
                        <Circle className="h-3 w-3" />
                      }
                      label={t('tasks.status')}
                      value={t(values.status === 'todo' ? 'tasks.toDo' : values.status === 'in_progress' ? 'tasks.inProgress' : 'tasks.done')}
                    />
                  </span>
                </PopoverTrigger>
                <PopoverContent className="w-40 p-1" align="start">
                  {(['todo', 'in_progress', 'done'] as const).map((s) => (
                    <button
                      key={s}
                      type="button"
                      onClick={() => setValues((v) => ({ ...v, status: s }))}
                      className="w-full text-left px-2 py-1.5 text-sm rounded hover:bg-accent/50"
                    >
                      {t(s === 'todo' ? 'tasks.toDo' : s === 'in_progress' ? 'tasks.inProgress' : 'tasks.done')}
                    </button>
                  ))}
                </PopoverContent>
              </Popover>

              {/* Due date */}
              <Popover>
                <PopoverTrigger asChild>
                  <span>
                    <PropertyPill
                      icon={<CalIcon className="h-3 w-3" />}
                      label={t('tasks.colDue')}
                      value={values.dueDate ? formatDueDate(values.dueDate, prefs) : null}
                      empty={!values.dueDate}
                    />
                  </span>
                </PopoverTrigger>
                <PopoverContent className="w-auto p-0" align="start">
                  <Calendar
                    mode="single"
                    selected={values.dueDate ? new Date(values.dueDate) : undefined}
                    timeZone={prefs.timezone}
                    onSelect={(d) => {
                      if (!d) {
                        setValues((v) => ({ ...v, dueDate: null }));
                        return;
                      }
                      // Preserve current H/M if any; otherwise default to 00:00 in user tz.
                      const cur = derivePartsInTz(values.dueDate, prefs.timezone);
                      const tz = new TZDate(
                        d.getFullYear(),
                        d.getMonth(),
                        d.getDate(),
                        cur?.hour ?? 0,
                        cur?.minute ?? 0,
                        0,
                        0,
                        prefs.timezone,
                      );
                      setValues((v) => ({ ...v, dueDate: tz.getTime() }));
                    }}
                  />
                  <div className="border-t px-3 py-2 flex flex-col gap-2">
                    <div>
                      <label className="text-xs text-muted-foreground mb-1 block">
                        {t('tasks.timeOptional')}
                      </label>
                      <div className="flex items-center gap-1.5">
                        <Select
                          value={dueHour}
                          onValueChange={(h) => updateDueTime(h, dueMinute || '00')}
                          disabled={!values.dueDate}
                        >
                          <SelectTrigger className="h-8 w-20 text-sm">
                            <SelectValue placeholder="HH" />
                          </SelectTrigger>
                          <SelectContent>
                            {HOURS.map((h) => (
                              <SelectItem key={h} value={h}>{h}</SelectItem>
                            ))}
                          </SelectContent>
                        </Select>
                        <span className="text-muted-foreground text-sm">:</span>
                        <Select
                          value={dueMinute}
                          onValueChange={(m) => updateDueTime(dueHour || '00', m)}
                          disabled={!values.dueDate}
                        >
                          <SelectTrigger className="h-8 w-20 text-sm">
                            <SelectValue placeholder="MM" />
                          </SelectTrigger>
                          <SelectContent>
                            {MINUTES.map((m) => (
                              <SelectItem key={m} value={m}>{m}</SelectItem>
                            ))}
                          </SelectContent>
                        </Select>
                        {values.dueDate && (dueHour !== '00' || dueMinute !== '00') && (
                          <Button
                            type="button"
                            variant="ghost"
                            size="sm"
                            className="h-8 px-2 text-xs"
                            onClick={() => updateDueTime('00', '00')}
                          >
                            {t('common.clear')}
                          </Button>
                        )}
                      </div>
                    </div>
                  </div>
                </PopoverContent>
              </Popover>

              {/* Assignees */}
              <Popover>
                <PopoverTrigger asChild>
                  <span>
                    <PropertyPill
                      icon={<UserPlus className="h-3 w-3" />}
                      label={t('tasks.assignees')}
                      value={values.assignees.length > 0 ? values.assignees.join(', ') : null}
                      empty={values.assignees.length === 0}
                    />
                  </span>
                </PopoverTrigger>
                <PopoverContent className="w-64 p-2" align="start">
                  <div className="flex flex-col gap-1 max-h-40 overflow-y-auto">
                    {knownAssignees.map((name) => (
                      <button
                        key={name}
                        type="button"
                        onClick={() => setValues((v) => ({
                          ...v,
                          assignees: v.assignees.includes(name)
                            ? v.assignees.filter((a) => a !== name)
                            : [...v.assignees, name],
                        }))}
                        className="text-left px-2 py-1.5 text-sm rounded hover:bg-accent/50"
                      >
                        {values.assignees.includes(name) ? '✓ ' : '   '}{name}
                      </button>
                    ))}
                  </div>
                  <div className="border-t mt-2 pt-2 flex gap-1.5">
                    <Input
                      placeholder={t('tasks.newAssigneeName', 'New name…')}
                      value={assigneeInput}
                      onChange={(e) => setAssigneeInput(e.target.value)}
                      onKeyDown={(e) => {
                        if (e.key === 'Enter') {
                          e.preventDefault();
                          addNewAssignee();
                        }
                      }}
                      className="h-8 text-sm flex-1"
                    />
                    <Button
                      type="button"
                      size="sm"
                      onClick={addNewAssignee}
                      disabled={!assigneeInput.trim()}
                    >
                      {t('common.add')}
                    </Button>
                  </div>
                </PopoverContent>
              </Popover>
            </div>
          </div>

          <div className="flex items-center justify-between gap-2 px-5 py-3 border-t border-border/40 bg-background/30">
            <div>
              {mode === 'edit' && taskId && (
                <Button
                  type="button"
                  variant="outline"
                  size="icon"
                  className="h-8 w-8"
                  onClick={() => attachments.addFiles()}
                  title={t('tasks.addFile')}
                >
                  <Paperclip className="h-4 w-4" />
                </Button>
              )}
            </div>
            <div className="flex items-center gap-2">
              <Button type="button" variant="outline" size="sm" onClick={() => onOpenChange(false)}>
                {t('common.cancel')}
              </Button>
              <Button type="submit" size="sm" disabled={!values.title.trim() || isSubmitting}>
                {isSubmitting
                  ? t('common.saving')
                  : mode === 'create'
                  ? t('tasks.createTask')
                  : t('common.save')}
              </Button>
            </div>
          </div>
        </form>
      </DialogContent>
    </Dialog>
  );
}
