import React, { useState, useEffect, useCallback, useMemo } from 'react';
import { useParams, useNavigate, useSearchParams } from 'react-router-dom';
import {
  FaArrowLeft, FaSave, FaEdit, FaTimes, FaPlus, FaTrash,
  FaCheckCircle, FaTimesCircle, FaSpinner, FaBullhorn, FaPaperPlane,
} from 'react-icons/fa';
import { toast, ToastContainer } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import projectUpdateService, { type ProjectUpdate, type ProjectUpdateUserRow } from '../services/projectUpdateService';
import apiService from '../services/apiService';
import LinkField from '../components/LinkField';
import ActivityLog from '../components/ActivityLog';

const FL: React.FC<{ children: React.ReactNode; required?: boolean }> = ({ children, required }) => (
  <label className="block text-xs font-semibold text-gray-500 dark:text-gray-400 uppercase tracking-wide mb-1">
    {children}{required && <span className="text-red-500 ml-0.5">*</span>}
  </label>
);
const RV: React.FC<{ children?: React.ReactNode }> = ({ children }) => (
  <div className="px-3 py-2 text-sm text-gray-800 dark:text-gray-200 bg-gray-50 dark:bg-gray-800/60 rounded-lg min-h-[38px] flex items-center">
    {children || <span className="text-gray-400">—</span>}
  </div>
);
const inputCls = 'w-full px-3 py-2 text-sm border border-gray-300 dark:border-gray-600 rounded-lg bg-white dark:bg-gray-700 text-gray-900 dark:text-white focus:outline-none focus:ring-2 focus:ring-violet-400';

function ymdToday(): string {
  return new Date().toISOString().slice(0, 10);
}

function timeNowShort(): string {
  const d = new Date();
  const h = String(d.getHours()).padStart(2, '0');
  const m = String(d.getMinutes()).padStart(2, '0');
  const s = String(d.getSeconds()).padStart(2, '0');
  return `${h}:${m}:${s}`;
}

const ProjectUpdateDetail: React.FC = () => {
  const { updateName } = useParams<{ updateName: string }>();
  const [searchParams] = useSearchParams();
  const navigate = useNavigate();
  const isNew = updateName === 'new';
  const prefProject = searchParams.get('project') || '';

  const [doc, setDoc] = useState<ProjectUpdate | null>(null);
  const [loading, setLoading] = useState(!isNew);
  const [saving, setSaving] = useState(false);
  const [submitting, setSubmitting] = useState(false);
  const [isEditing, setIsEditing] = useState(isNew);
  const [error, setError] = useState('');

  const emptyForm: Partial<ProjectUpdate> & { users: ProjectUpdateUserRow[] } = useMemo(
    () => ({
      project: prefProject,
      sent: 0,
      date: ymdToday(),
      time: timeNowShort(),
      users: [],
    }),
    [prefProject],
  );

  const [form, setForm] = useState(emptyForm);

  const syncForm = useCallback((u: ProjectUpdate) => {
    setForm({
      project: u.project || '',
      sent: u.sent ?? 0,
      date: (u.date || '').slice(0, 10) || ymdToday(),
      time: u.time ? String(u.time).slice(0, 8) : timeNowShort(),
      users: Array.isArray(u.users) ? u.users.map(r => ({ ...r })) : [],
    });
  }, []);

  useEffect(() => {
    if (!isNew && updateName) {
      setLoading(true);
      projectUpdateService
        .getProjectUpdate(updateName)
        .then((u) => {
          setDoc(u);
          syncForm(u);
        })
        .catch((e) => setError(e instanceof Error ? e.message : 'Load failed'))
        .finally(() => setLoading(false));
    }
  }, [updateName, isNew, syncForm]);

  const set = (k: keyof ProjectUpdate, v: any) => setForm(f => ({ ...f, [k]: v }));

  const docLocked = !isNew && doc?.docstatus === 1;
  const editable = (isNew || isEditing) && !docLocked;

  const addUserRow = () => {
    setForm(f => ({
      ...f,
      users: [...(f.users || []), { user: '', email: '', full_name: '' }],
    }));
  };

  const removeUserRow = (idx: number) => {
    setForm(f => ({
      ...f,
      users: (f.users || []).filter((_, i) => i !== idx),
    }));
  };

  const setUserRow = (idx: number, patch: Partial<ProjectUpdateUserRow>) => {
    setForm(f => {
      const users = [...(f.users || [])];
      users[idx] = { ...users[idx], ...patch };
      return { ...f, users };
    });
  };

  const hydrateUserRowFromUserDoc = useCallback(async (idx: number, userId: string) => {
    if (!userId) return;
    try {
      const q = new URLSearchParams();
      q.set('fields', JSON.stringify(['email', 'full_name']));
      const res = await apiService.apiCall<{ name: string; email?: string; full_name?: string }>(
        `/api/resource/User/${encodeURIComponent(userId)}?${q.toString()}`,
      );
      // Frappe returns { data: {...} } when using /api/resource; apiCall unwraps message only,
      // so we also handle the common shape defensively.
      const data = (res as any)?.data ?? res;
      setUserRow(idx, {
        email: data?.email || userId,
        full_name: data?.full_name || '',
      });
    } catch {
      // Fallback: at least show the user id as email when it's an email-like login.
      setUserRow(idx, { email: userId });
    }
  }, []);

  const payloadFromForm = (): Partial<ProjectUpdate> => {
    const users = (form.users || [])
      .filter(r => (r.user || '').trim())
      .map((r, i) => ({
        doctype: 'Project User',
        ...r,
        idx: i + 1,
      }));
    return {
      project: form.project?.trim() || undefined,
      sent: form.sent ? 1 : 0,
      date: form.date || undefined,
      time: form.time || undefined,
      users,
    };
  };

  const handleSave = async () => {
    if (!form.project?.trim()) {
      toast.error('Project is required');
      return;
    }
    setSaving(true);
    try {
      const body = payloadFromForm();
      if (isNew) {
        const created = await projectUpdateService.createProjectUpdate(body);
        toast.success('Project update created', { icon: <FaCheckCircle /> });
        navigate(`/projects/project-updates/${encodeURIComponent(created.name)}`, { replace: true });
      } else {
        const updated = await projectUpdateService.updateProjectUpdate(updateName!, body);
        toast.success('Saved', { icon: <FaCheckCircle /> });
        setDoc(updated);
        syncForm(updated);
        setIsEditing(false);
      }
    } catch (e) {
      toast.error(e instanceof Error ? e.message : 'Save failed', { icon: <FaTimesCircle /> });
    } finally {
      setSaving(false);
    }
  };

  const handleSubmit = async () => {
    if (isNew || !updateName) return;
    setSubmitting(true);
    try {
      const submitted = await projectUpdateService.submitProjectUpdate(updateName);
      toast.success('Submitted', { icon: <FaCheckCircle /> });
      setDoc(submitted);
      syncForm(submitted);
      setIsEditing(false);
    } catch (e) {
      toast.error(e instanceof Error ? e.message : 'Submit failed', { icon: <FaTimesCircle /> });
    } finally {
      setSubmitting(false);
    }
  };

  const handleCancel = () => {
    if (doc) syncForm(doc);
    setIsEditing(false);
  };

  if (loading) {
    return (
      <div className="flex justify-center items-center min-h-[400px]">
        <FaSpinner className="animate-spin text-violet-500 text-3xl" />
      </div>
    );
  }

  if (!isNew && error) {
    return (
      <div className="p-6">
        <button type="button" onClick={() => navigate('/projects/project-updates')} className="flex items-center gap-2 text-gray-600 mb-4">
          <FaArrowLeft /> Back
        </button>
        <div className="p-4 bg-red-50 dark:bg-red-900/20 rounded-lg text-red-700">{error}</div>
      </div>
    );
  }

  return (
    <div className="min-h-screen bg-gray-50 dark:bg-gray-900 px-6 py-6">
      <ToastContainer position="top-right" autoClose={3500} />

      <div className="flex items-center gap-2 text-xs text-gray-400 mb-4">
        <button type="button" onClick={() => navigate('/projects')} className="hover:text-violet-600">Project Management</button>
        <span>/</span>
        <button type="button" onClick={() => navigate('/projects/project-updates')} className="hover:text-violet-600">Project updates</button>
        <span>/</span>
        <span className="text-gray-600 dark:text-gray-300">{isNew ? 'New' : updateName}</span>
      </div>

      <div className="flex flex-col sm:flex-row sm:items-start sm:justify-between gap-4 mb-6">
        <div className="flex items-start gap-3">
          <button
            type="button"
            onClick={() => navigate('/projects/project-updates')}
            className="mt-1 p-2 rounded-lg text-gray-400 hover:text-gray-700 dark:hover:text-gray-200 border border-gray-200 dark:border-gray-600"
          >
            <FaArrowLeft size={14} />
          </button>
          <div className="w-11 h-11 rounded-xl bg-gradient-to-br from-violet-500 to-purple-700 flex items-center justify-center shadow-md">
            <FaBullhorn className="text-white text-lg" />
          </div>
          <div>
            <h1 className="text-xl font-bold text-gray-900 dark:text-white">
              {isNew ? 'New project update' : (doc?.name || updateName)}
            </h1>
            {!isNew && doc && (
              <p className="text-xs text-gray-500 mt-1">
                <span className={`font-medium ${doc.docstatus === 1 ? 'text-green-600' : 'text-amber-600'}`}>
                  {doc.docstatus === 1 ? 'Submitted' : 'Draft'}
                </span>
                {doc.project && (
                  <>
                    <span className="mx-2">·</span>
                    <button
                      type="button"
                      className="text-violet-600 hover:underline font-mono"
                      onClick={() => navigate(`/projects/list/${encodeURIComponent(doc.project!)}`)}
                    >
                      {doc.project}
                    </button>
                  </>
                )}
              </p>
            )}
          </div>
        </div>

        <div className="flex flex-wrap gap-2">
          {!isNew && !docLocked && !isEditing && (
            <button
              type="button"
              onClick={() => setIsEditing(true)}
              className="flex items-center gap-2 px-4 py-2 bg-blue-600 hover:bg-blue-700 text-white rounded-lg text-sm font-medium shadow"
            >
              <FaEdit size={12} /> Edit
            </button>
          )}
          {(isNew || isEditing) && !docLocked && (
            <>
              <button
                type="button"
                onClick={handleSave}
                disabled={saving}
                className="flex items-center gap-2 px-4 py-2 bg-violet-600 hover:bg-violet-700 text-white rounded-lg text-sm font-medium disabled:opacity-50"
              >
                {saving ? <FaSpinner className="animate-spin" size={12} /> : <FaSave size={12} />}
                {saving ? 'Saving…' : 'Save'}
              </button>
              {!isNew && (
                <button type="button" onClick={handleCancel} className="flex items-center gap-2 px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-lg text-sm text-gray-600 dark:text-gray-300">
                  <FaTimes size={12} /> Cancel
                </button>
              )}
            </>
          )}
          {!isNew && !docLocked && doc?.docstatus === 0 && (
            <button
              type="button"
              onClick={handleSubmit}
              disabled={submitting}
              className="flex items-center gap-2 px-4 py-2 bg-green-600 hover:bg-green-700 text-white rounded-lg text-sm font-medium disabled:opacity-50"
            >
              {submitting ? <FaSpinner className="animate-spin" size={12} /> : <FaPaperPlane size={12} />}
              Submit
            </button>
          )}
        </div>
      </div>

      <div className="space-y-4 max-w-4xl">
        <div className="bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 p-5 shadow-sm">
          <h2 className="text-sm font-semibold text-gray-700 dark:text-gray-200 mb-4">Details</h2>
          <div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
            <div className="sm:col-span-2">
              <FL required>Project</FL>
              {editable
                ? <LinkField label="Project" hideLabel doctype="Project" value={form.project || ''} onChange={v => set('project', v)} placeholder="Select project…" />
                : <RV>{form.project || '—'}</RV>}
            </div>
            <div>
              <FL>Date</FL>
              {editable
                ? <input type="date" className={inputCls} value={form.date || ''} onChange={e => set('date', e.target.value)} />
                : <RV>{form.date || '—'}</RV>}
            </div>
            <div>
              <FL>Time</FL>
              {editable
                ? <input type="time" step={1} className={inputCls} value={(form.time || '').slice(0, 8)} onChange={e => set('time', e.target.value)} />
                : <RV>{form.time || '—'}</RV>}
            </div>
            <div className="sm:col-span-2 flex items-center gap-3">
              <input
                id="sent"
                type="checkbox"
                className="w-4 h-4 text-violet-600 rounded border-gray-300"
                checked={!!form.sent}
                disabled={!editable}
                onChange={e => set('sent', e.target.checked ? 1 : 0)}
              />
              <label htmlFor="sent" className={`text-sm font-medium text-gray-700 dark:text-gray-300 ${editable ? 'cursor-pointer' : ''}`}>
                Sent
              </label>
            </div>
          </div>
        </div>

        <div className="bg-white dark:bg-gray-800 rounded-xl border border-gray-200 dark:border-gray-700 p-5 shadow-sm">
          <div className="flex items-center justify-between mb-4">
            <h2 className="text-sm font-semibold text-gray-700 dark:text-gray-200">Users</h2>
            {editable && (
              <button type="button" onClick={addUserRow} className="text-xs font-semibold text-violet-600 flex items-center gap-1 hover:underline">
                <FaPlus size={10} /> Add user
              </button>
            )}
          </div>
          {(form.users || []).length === 0 ? (
            <p className="text-sm text-gray-500">No users added.</p>
          ) : (
            <div className="space-y-3">
              {(form.users || []).map((row, idx) => (
                <div key={idx} className="flex flex-col sm:flex-row gap-2 sm:items-end p-3 rounded-lg border border-gray-100 dark:border-gray-700 bg-gray-50/50 dark:bg-gray-900/20">
                  <div className="flex-1 min-w-0">
                    <FL>User</FL>
                    {editable
                      ? (
                        <LinkField
                          label="User"
                          hideLabel
                          doctype="User"
                          value={row.user || ''}
                          onChange={(v) => {
                            setUserRow(idx, { user: v, email: '', full_name: '' });
                            hydrateUserRowFromUserDoc(idx, v);
                          }}
                          placeholder="Select user…"
                        />
                      )
                      : <RV><span className="font-mono text-xs">{row.user || '—'}</span></RV>}
                  </div>
                  <div className="flex-1 min-w-0">
                    <FL>Email</FL>
                    <RV><span className="text-xs">{row.email || '—'}</span></RV>
                  </div>
                  <div className="flex-1 min-w-0">
                    <FL>Full name</FL>
                    <RV><span className="text-xs">{row.full_name || '—'}</span></RV>
                  </div>
                  {editable && (
                    <button type="button" onClick={() => removeUserRow(idx)} className="p-2 text-red-500 hover:bg-red-50 dark:hover:bg-red-900/20 rounded-lg self-end sm:self-center" title="Remove row">
                      <FaTrash size={12} />
                    </button>
                  )}
                </div>
              ))}
            </div>
          )}
        </div>

        {!isNew && updateName && (
          <ActivityLog doctype="Project Update" docname={updateName} />
        )}
      </div>
    </div>
  );
};

export default ProjectUpdateDetail;
