import type { WidgetRegistryMeta } from 'officerdev';
import { useCallback, useRef, useState } from 'react';
import { useQueryClient, useQuery } from '@tanstack/react-query';
import { useClient } from 'hooks/useClient';
import { useAuth } from 'hooks/useAuth';
import { Plus, Target, Trash2, Flame } from 'lucide-react';
import { Widget } from '../Widget';

type Goal = {
  id: string;
  text: string;
  done: boolean;
};

type DailyGoalsState = {
  goals: Goal[];
  lastDate: string;
  streak: number;
  lastCompletedDate: string | null;
};

const USER_STATE_KEY = ['USER_STATE'];
const GOALS_STATE_KEY = 'daily-goals';

const todayStr = () => new Date().toISOString().slice(0, 10);
const yesterdayStr = () => {
  const d = new Date();
  d.setDate(d.getDate() - 1);
  return d.toISOString().slice(0, 10);
};

function useDailyGoalsState() {
  const client = useClient();
  const { isAuthenticated } = useAuth();
  const queryClient = useQueryClient();
  const clientRef = useRef(client);
  clientRef.current = client;

  const { data: userState = {} } = useQuery<Record<string, unknown>>({
    queryKey: USER_STATE_KEY,
    enabled: isAuthenticated,
    queryFn: () => client.get('/user/state'),
    staleTime: Infinity,
  });

  const stored = userState[GOALS_STATE_KEY] as DailyGoalsState | undefined;
  const today = todayStr();

  const state: DailyGoalsState = (() => {
    if (!stored) return { goals: [], lastDate: today, streak: 0, lastCompletedDate: null };
    if (stored.lastDate === today) return stored;

    // New day — check if yesterday had all goals completed for streak
    const allDoneYesterday = stored.goals.length > 0 && stored.goals.every((g) => g.done);
    const wasYesterday = stored.lastDate === yesterdayStr();
    const streak = allDoneYesterday && wasYesterday ? stored.streak + 1 : allDoneYesterday ? 1 : 0;
    const lastCompletedDate = allDoneYesterday ? stored.lastDate : stored.lastCompletedDate;

    return {
      goals: stored.goals.map((g) => ({ ...g, done: false })),
      lastDate: today,
      streak,
      lastCompletedDate,
    };
  })();

  const setState = useCallback(
    (update: DailyGoalsState | ((prev: DailyGoalsState) => DailyGoalsState)) => {
      const currentUserState = queryClient.getQueryData<Record<string, unknown>>(USER_STATE_KEY) ?? {};
      const current = (currentUserState[GOALS_STATE_KEY] as DailyGoalsState | undefined) ?? state;
      const next = typeof update === 'function' ? update(current) : update;
      queryClient.setQueryData(USER_STATE_KEY, { ...currentUserState, [GOALS_STATE_KEY]: next });
      clientRef.current.patch('/user/state', { [GOALS_STATE_KEY]: next }).catch(() => {});
    },
    [queryClient, state],
  );

  return [state, setState] as const;
}

let nextGoalId = Date.now();

export const DailyGoals = () => {
  const [state, setState] = useDailyGoalsState();
  const [newGoal, setNewGoal] = useState('');
  const inputRef = useRef<HTMLInputElement>(null);

  const addGoal = () => {
    const text = newGoal.trim();
    if (!text) return;
    nextGoalId++;
    setState((s) => ({
      ...s,
      goals: [...s.goals, { id: String(nextGoalId), text, done: false }],
    }));
    setNewGoal('');
    inputRef.current?.focus();
  };

  const toggleGoal = (id: string) => {
    setState((s) => ({
      ...s,
      goals: s.goals.map((g) => (g.id === id ? { ...g, done: !g.done } : g)),
    }));
  };

  const removeGoal = (id: string) => {
    setState((s) => ({
      ...s,
      goals: s.goals.filter((g) => g.id !== id),
    }));
  };

  const { goals, streak } = state;
  const doneCount = goals.filter((g) => g.done).length;

  return (
    <Widget title="Daily Goals">
      <div className="flex flex-col gap-2 px-4 pb-4">
        {streak > 0 && (
          <div className="flex items-center gap-1.5 text-xs text-warning">
            <Flame size={12} />
            <span>{streak} day streak</span>
          </div>
        )}

        {goals.length > 0 && (
          <div className="flex flex-col gap-1">
            {goals.map((goal) => (
              <div key={goal.id} className="group flex items-center gap-2">
                <button
                  type="button"
                  className={`flex h-4 w-4 shrink-0 items-center justify-center rounded border cursor-pointer transition-colors ${
                    goal.done ? 'border-primary bg-primary text-primary-foreground' : 'border-border hover:border-primary'
                  }`}
                  onClick={() => toggleGoal(goal.id)}
                >
                  {goal.done && (
                    <svg width="10" height="10" viewBox="0 0 10 10">
                      <path d="M2 5l2.5 2.5L8 3" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
                    </svg>
                  )}
                </button>
                <span className={`flex-1 text-sm ${goal.done ? 'line-through text-muted-foreground' : ''}`}>
                  {goal.text}
                </span>
                <button
                  type="button"
                  className="p-0.5 rounded cursor-pointer text-muted-foreground opacity-0 hover:text-destructive group-hover:opacity-100 transition-opacity"
                  onClick={() => removeGoal(goal.id)}
                >
                  <Trash2 size={12} />
                </button>
              </div>
            ))}
          </div>
        )}

        {goals.length > 0 && (
          <div className="text-[10px] text-muted-foreground">
            {doneCount}/{goals.length} completed
          </div>
        )}

        <div className="flex items-center gap-1">
          <input
            ref={inputRef}
            type="text"
            placeholder="Add a goal..."
            value={newGoal}
            onChange={(ev) => setNewGoal(ev.target.value)}
            onKeyDown={(ev) => {
              if (ev.key === 'Enter') {
                ev.preventDefault();
                addGoal();
              }
            }}
            className="flex-1 rounded-md border border-border bg-background px-2 py-1 text-xs outline-none focus:ring-1 focus:ring-ring"
          />
          <button
            type="button"
            className="flex h-6 w-6 items-center justify-center rounded-md border border-border hover:bg-accent transition-colors cursor-pointer"
            onClick={addGoal}
          >
            <Plus size={12} />
          </button>
        </div>
      </div>
    </Widget>
  );
};

export const widgetRegistryMetas: WidgetRegistryMeta[] = [
  { key: 'daily-goals', name: 'Daily Goals', icon: Target, component: DailyGoals },
];
