/**
 * Rule editor — condition builder + action selector for mail rules.
 */

import React, { useState, useEffect, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { z } from 'zod';
import { Button } from '@/components/ui/Button';
import { Input } from '@/components/ui/Input';
import { Select } from '@/components/ui/Select';
import { Card } from '@/components/ui/Card';
import { EmptyState } from '@/components/ui/EmptyState';
import { useToast } from '@/components/ui/Toast';
import { ConfirmDialog } from '@/components/ui/ConfirmDialog';

import { Loader2 } from 'lucide-react';
import {
  fetchRules,
  createRule,
  deleteRule,
  type MailRule,
  type RuleCondition,
  type RuleAction,
  type RuleConditionType,
  type RuleActionType,
} from '@/api/mail';

const conditionTypeOptions = (t: (s: string) => string) => [
  { value: 'from_contains', label: t('mail.ruleCondFromContains') },
  { value: 'to_contains', label: t('mail.ruleCondToContains') },
  { value: 'subject_contains', label: t('mail.ruleCondSubjectContains') },
  { value: 'body_contains', label: t('mail.ruleCondBodyContains') },
  { value: 'has_attachment', label: t('mail.ruleCondHasAttachment') },
];

const actionTypeOptions = (t: (s: string) => string) => [
  { value: 'move_to_folder', label: t('mail.ruleActionMoveToFolder') },
  { value: 'mark_as_read', label: t('mail.ruleActionMarkAsRead') },
  { value: 'mark_as_flagged', label: t('mail.ruleActionMarkAsFlagged') },
  { value: 'forward_to', label: t('mail.ruleActionForwardTo') },
  { value: 'delete', label: t('mail.ruleActionDelete') },
];

export function RuleEditor({ accountId }: { accountId: string }) {
  const { t } = useTranslation();
  const toast = useToast();
  const [rules, setRules] = useState<MailRule[]>([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const [showForm, setShowForm] = useState(false);
  const [conditions, setConditions] = useState<RuleCondition[]>([{ type: 'from_contains', value: '' }]);
  const [actions, setActions] = useState<RuleAction[]>([{ type: 'mark_as_read', value: '' }]);
  const [saving, setSaving] = useState(false);
  const [deleteTarget, setDeleteTarget] = useState<MailRule | null>(null);

  // ── Rule form (RHF + Zod) ──
  const ruleSchema = z.object({
    name: z.string().min(1, 'required'),
    priority: z.coerce.number().int().min(1, 'invalidNumber').default(1),
  });
  type RuleFormData = z.infer<typeof ruleSchema>;

  const { register: registerRule, handleSubmit: handleSubmitRule, reset: resetRule, formState: { errors: ruleErrors } } = useForm<RuleFormData>({
    resolver: zodResolver(ruleSchema),
    defaultValues: { name: '', priority: 1 },
  });

  const load = useCallback(() => {
    setLoading(true);
    fetchRules()
      .then((data) => {
        setRules(data);
        setError(null);
      })
      .catch((err) => {
        setError(err instanceof Error ? err.message : String(err));
      })
      .finally(() => setLoading(false));
  }, []);

  useEffect(() => { load(); }, [load]);

  const addCondition = () => {
    setConditions((prev) => [...prev, { type: 'from_contains', value: '' }]);
  };

  const updateCondition = (index: number, field: 'type' | 'value', val: string) => {
    setConditions((prev) => prev.map((c, i) => (i === index ? { ...c, [field]: val } : c)));
  };

  const removeCondition = (index: number) => {
    setConditions((prev) => prev.filter((_, i) => i !== index));
  };

  const addAction = () => {
    setActions((prev) => [...prev, { type: 'mark_as_read', value: '' }]);
  };

  const updateAction = (index: number, field: 'type' | 'value', val: string) => {
    setActions((prev) => prev.map((a, i) => (i === index ? { ...a, [field]: val } : a)));
  };

  const removeAction = (index: number) => {
    setActions((prev) => prev.filter((_, i) => i !== index));
  };

  const handleSave = useCallback(async (data: RuleFormData) => {
    setSaving(true);
    try {
      const rule = await createRule({
        name: data.name,
        account_id: accountId,
        priority: data.priority,
        is_active: true,
        conditions,
        actions,
      });
      setRules((prev) => [...prev, rule].sort((a, b) => a.priority - b.priority));
      toast.success(t('mail.ruleCreated'));
      setShowForm(false);
      resetRule({ name: '', priority: 1 });
      setConditions([{ type: 'from_contains', value: '' }]);
      setActions([{ type: 'mark_as_read', value: '' }]);
    } catch (err) {
      toast.error(err instanceof Error ? err.message : String(err));
    } finally {
      setSaving(false);
    }
  }, [accountId, conditions, actions, toast, t, resetRule]);

  const handleDelete = useCallback(async () => {
    if (!deleteTarget) return;
    try {
      await deleteRule(deleteTarget.id);
      setRules((prev) => prev.filter((r) => r.id !== deleteTarget.id));
      toast.success(t('mail.ruleDeleted'));
      setDeleteTarget(null);
    } catch (err) {
      toast.error(err instanceof Error ? err.message : String(err));
    }
  }, [deleteTarget, toast, t]);

  if (loading) {
    return (
      <div className="flex items-center justify-center py-8" data-testid="rule-editor-loading">
        <Loader2 className="animate-spin h-5 w-5 text-secondary-400" aria-hidden="true" />
      </div>
    );
  }

  if (error) {
    return (
      <div className="p-4 bg-danger-50 border border-danger-200 rounded-md" role="alert" data-testid="rule-editor-error">
        <p className="text-sm text-danger-700">{error}</p>
      </div>
    );
  }

  return (
    <div data-testid="rule-editor">
      <div className="flex items-center justify-between mb-4">
        <h3 className="text-lg font-semibold text-secondary-900">{t('mail.rules')}</h3>
        <Button size="sm" onClick={() => setShowForm(!showForm)} data-testid="new-rule-btn">{t('mail.newRule')}</Button>
      </div>

      {showForm && (
        <Card className="mb-4" data-testid="rule-form">
          <form onSubmit={handleSubmitRule(handleSave)} className="space-y-4">
            <Input
              label={t('mail.ruleName')}
              {...registerRule('name')}
              error={ruleErrors.name?.message === 'required' ? t('validation.required') : undefined}
              placeholder={t('mail.ruleName')}
              required
            />
            <Input
              label={t('mail.rulePriority')}
              type="number"
              {...registerRule('priority')}
              error={ruleErrors.priority?.message === 'invalidNumber' ? t('validation.invalidNumber', 'Invalid number') : undefined}
            />

            {/* Conditions */}
            <div>
              <p className="text-sm font-medium text-secondary-700 mb-2">{t('mail.ruleConditions')}</p>
              <div className="space-y-2" data-testid="rule-conditions">
                {conditions.map((cond, idx) => (
                  <div key={idx} className="flex items-center gap-2">
                    <Select
                      value={cond.type}
                      onChange={(e) => updateCondition(idx, 'type', e.target.value as RuleConditionType)}
                      options={conditionTypeOptions(t)}
                      className="flex-1"
                    />
                    {cond.type !== 'has_attachment' && (
                      <Input
                        value={cond.value}
                        onChange={(e) => updateCondition(idx, 'value', e.target.value)}
                        placeholder={t('mail.ruleCondValue')}
                        className="flex-1"
                      />
                    )}
                    <Button variant="ghost" size="sm" onClick={() => removeCondition(idx)} type="button">−</Button>
                  </div>
                ))}
              </div>
              <Button variant="secondary" size="sm" onClick={addCondition} className="mt-2" type="button">{t('mail.addCondition')}</Button>
            </div>

            {/* Actions */}
            <div>
              <p className="text-sm font-medium text-secondary-700 mb-2">{t('mail.ruleActions')}</p>
              <div className="space-y-2" data-testid="rule-actions">
                {actions.map((act, idx) => (
                  <div key={idx} className="flex items-center gap-2">
                    <Select
                      value={act.type}
                      onChange={(e) => updateAction(idx, 'type', e.target.value as RuleActionType)}
                      options={actionTypeOptions(t)}
                      className="flex-1"
                    />
                    {(act.type === 'move_to_folder' || act.type === 'forward_to') && (
                      <Input
                        value={act.value}
                        onChange={(e) => updateAction(idx, 'value', e.target.value)}
                        placeholder={t('mail.ruleActionValue')}
                        className="flex-1"
                      />
                    )}
                    <Button variant="ghost" size="sm" onClick={() => removeAction(idx)} type="button">−</Button>
                  </div>
                ))}
              </div>
              <Button variant="secondary" size="sm" onClick={addAction} className="mt-2" type="button">{t('mail.addAction')}</Button>
            </div>

            <div className="flex gap-2">
              <Button type="submit" isLoading={saving} size="sm">{t('common.save')}</Button>
              <Button variant="secondary" size="sm" type="button" onClick={() => setShowForm(false)}>{t('common.cancel')}</Button>
            </div>
          </form>
        </Card>
      )}

      {rules.length === 0 && !showForm ? (
        <EmptyState title={t('mail.noRules')} description={t('mail.noRulesDesc')} />
      ) : (
        <div className="space-y-2" data-testid="rule-list">
          {rules.map((rule) => (
            <Card key={rule.id}>
              <div className="flex items-center justify-between">
                <div className="flex-1">
                  <div className="flex items-center gap-2">
                    <span className="text-xs text-secondary-400">#{rule.priority}</span>
                    <p className="font-medium text-secondary-900">{rule.name}</p>
                  </div>
                  <p className="text-sm text-secondary-500 mt-1">
                    {rule.conditions.length} {t('mail.ruleConditions')} → {rule.actions.length} {t('mail.ruleActions')}
                  </p>
                </div>
                <Button variant="danger" size="sm" onClick={() => setDeleteTarget(rule)} data-testid={`delete-rule-${rule.id}`}>{t('common.delete')}</Button>
              </div>
            </Card>
          ))}
        </div>
      )}

      <ConfirmDialog
        open={!!deleteTarget}
        title={t('mail.deleteRule')}
        message={t('mail.confirmDeleteRule')}
        confirmLabel={t('common.delete')}
        variant="danger"
        onConfirm={handleDelete}
        onCancel={() => setDeleteTarget(null)}
      />
    </div>
  );
}