const { useState, useEffect, useMemo } = React;

// Lightweight inline icons (SVG) to avoid external deps
const Icon = ({ path, size = 20, className = '' }) => (
  <svg xmlns="http://www.w3.org/2000/svg" width={size} height={size} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" className={className}>
    <path d={path} />
  </svg>
);
const ChevronLeft = (p) => <Icon {...p} path="M15 18l-6-6 6-6" />;
const ChevronRight = (p) => <Icon {...p} path="M9 18l6-6-6-6" />;
const Save = (p) => <Icon {...p} path="M19 21H5a2 2 0 0 1-2-2V7l4-4h8l4 4v12a2 2 0 0 1-2 2z M17 21V10H7v11" />;
const Edit2 = (p) => <Icon {...p} path="M12 20h9" />;
const Check = (p) => <Icon {...p} path="M20 6L9 17l-5-5" />;
const CalendarIcon = (p) => <Icon {...p} path="M8 2v4M16 2v4M3 10h18M5 22h14a2 2 0 0 0 2-2V6H3v14a2 2 0 0 0 2 2z" />;
const Clock = (p) => <Icon {...p} path="M12 6v6l4 2M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0z" />;
const X = (p) => <Icon {...p} path="M18 6L6 18M6 6l12 12" />;

// Helper to format minutes into "Xh Ym"
const formatTime = (totalMinutes) => {
  if (!totalMinutes) return '0h 0m';
  const h = Math.floor(totalMinutes / 60);
  const m = totalMinutes % 60;
  return `${h}h ${m}m`;
};

function useAuth() {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);

  const refresh = async () => {
    try {
      const res = await fetch('api/me');
      if (res.ok) {
        const data = await res.json();
        setUser({ username: data.username });
      } else {
        setUser(null);
      }
    } catch (_) {
      setUser(null);
    } finally {
      setLoading(false);
    }
  };

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

  const login = async (username, password) => {
    const res = await fetch('api/login', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username, password }) });
    if (!res.ok) throw new Error('Invalid credentials');
    await refresh();
  };

  const register = async (username, password) => {
    const res = await fetch('api/register', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ username, password }) });
    if (!res.ok) {
      const d = await res.json().catch(() => ({}));
      throw new Error(d.error || 'Registration failed');
    }
    await refresh();
  };

  const logout = async () => {
    await fetch('api/logout', { method: 'POST' });
    setUser(null);
  };

  return { user, loading, login, register, logout };
}

function App() {
  const { user, loading: loadingUser, login, register, logout } = useAuth();
  const [monthData, setMonthData] = useState({ goalHours: 0, logs: {} });
  const [loadingData, setLoadingData] = useState(false);
  const [savePending, setSavePending] = useState(false);
  const [exporting, setExporting] = useState(false);

  const [currentDate, setCurrentDate] = useState(new Date());
  const [isEditingGoal, setIsEditingGoal] = useState(false);
  const [tempGoal, setTempGoal] = useState('');

  const year = currentDate.getFullYear();
  const month = currentDate.getMonth(); // 0-indexed
  const monthKey = `${year}-${String(month + 1).padStart(2, '0')}`;

  // Fetch data for current month when user or month changes
  useEffect(() => {
    if (!user) return;
    setLoadingData(true);
    fetch(`api/month?year=${year}&month=${month + 1}`)
      .then(r => r.json())
      .then(d => setMonthData({ goalHours: d?.goalHours || 0, logs: d?.logs || {} }))
      .catch(() => setMonthData({ goalHours: 0, logs: {} }))
      .finally(() => setLoadingData(false));
  }, [user?.username, year, month]);

  // Save to server whenever data changes (debounced)
  useEffect(() => {
    if (!user) return;
    const h = setTimeout(() => {
      setSavePending(true);
      fetch('api/month', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ year, month: month + 1, goalHours: monthData.goalHours, logs: monthData.logs }) })
        .finally(() => setSavePending(false));
    }, 300);
    return () => clearTimeout(h);
  }, [monthData, user?.username, year, month]);

  useEffect(() => {
    setTempGoal(monthData.goalHours || 0);
    setIsEditingGoal(false);
  }, [monthData.goalHours, monthKey]);

  const getDaysInMonth = (y, m) => new Date(y, m + 1, 0).getDate();
  const getFirstDayOfMonth = (y, m) => new Date(y, m, 1).getDay();

  const daysInMonth = getDaysInMonth(year, month);
  const startDay = getFirstDayOfMonth(year, month);

  const currentGoalHours = monthData.goalHours || 0;
  const currentGoalMinutes = currentGoalHours * 60;

  const totalMinutesWorked = useMemo(() => {
    let sum = 0;
    for (let d = 1; d <= daysInMonth; d++) {
      const dateKey = `${monthKey}-${String(d).padStart(2, '0')}`;
      sum += (monthData.logs[dateKey] || 0);
    }
    return sum;
  }, [monthData.logs, monthKey, daysInMonth]);

  const exportCsv = async () => {
    try {
      setExporting(true);
      const res = await fetch('api/export');
      if (!res.ok) throw new Error('Export failed');
      const blob = await res.blob();
      const url = URL.createObjectURL(blob);
      const a = document.createElement('a');
      a.href = url;
      const ts = new Date().toISOString().slice(0,19).replace(/[:T]/g,'-');
      a.download = `work_time_export_${user?.username || 'data'}_${ts}.csv`;
      document.body.appendChild(a);
      a.click();
      URL.revokeObjectURL(url);
      a.remove();
    } catch (_) {
      alert('Failed to export data.');
    } finally {
      setExporting(false);
    }
  };

  const percentage = currentGoalMinutes > 0 ? Math.min(100, Math.round((totalMinutesWorked / currentGoalMinutes) * 100)) : 0;
  const minutesLeft = Math.max(0, currentGoalMinutes - totalMinutesWorked);

  const handlePrevMonth = () => setCurrentDate(new Date(year, month - 1, 1));
  const handleNextMonth = () => setCurrentDate(new Date(year, month + 1, 1));

  const handleGoalSave = () => {
    const raw = parseFloat(String(tempGoal).replace(',', '.'));
    const gh = Number.isFinite(raw) ? Math.round(raw * 2) / 2 : 0; // allow half hours
    setMonthData(prev => ({ ...prev, goalHours: gh }));
    setIsEditingGoal(false);
  };

  const handleLogUpdate = (day, minutes) => {
    const dateKey = `${monthKey}-${String(day).padStart(2, '0')}`;
    setMonthData(prev => ({ ...prev, logs: { ...prev.logs, [dateKey]: minutes } }));
  };

  if (loadingUser || loadingData) return <div className="flex h-screen items-center justify-center text-slate-400">Loading...</div>;

  if (!user) return <AuthView onLogin={login} onRegister={register} />;

  return (
    <div className="min-h-screen bg-slate-50 text-slate-800 font-sans pb-20 md:pb-10">
      <div className="max-w-4xl mx-auto md:p-6 p-3 space-y-4">
        <header className="sticky top-0 z-30 bg-white/90 backdrop-blur-md p-4 rounded-2xl shadow-sm border border-slate-200/60 md:static">
          <div className="flex flex-col gap-4">
            <div className="flex items-center justify-between">
              <div className="flex items-center gap-3">
                <div className="p-2.5 bg-blue-600 rounded-xl text-white shadow-blue-200 shadow-md">
                  <CalendarIcon size={20} />
                </div>
                <div>
                  <h1 className="text-xl font-bold text-slate-900 leading-none">Work Tracker</h1>
                  <p className="text-xs text-slate-500 font-medium mt-1">Monthly Overview</p>
                </div>
              </div>
              <div className="flex items-center gap-2">
                <button onClick={exportCsv} disabled={exporting} className="text-xs px-2 py-1 bg-slate-100 rounded hover:bg-slate-200 disabled:opacity-50">
                  {exporting ? 'Exporting…' : 'Export CSV'}
                </button>
                <span className="text-xs text-slate-500">Signed in as <b>{user.username}</b></span>
                <button onClick={logout} className="text-xs px-2 py-1 bg-slate-100 rounded hover:bg-slate-200">Logout</button>
              </div>
            </div>
            <div className="flex items-center justify-between bg-slate-50 p-1.5 rounded-xl border border-slate-100">
              <button onClick={handlePrevMonth} className="p-3 bg-white shadow-sm rounded-lg text-slate-600 hover:text-blue-600 active:scale-95 transition-all" aria-label="Previous Month">
                <ChevronLeft size={20} />
              </button>
              <div className="font-bold text-lg text-slate-800 tabular-nums">
                {currentDate.toLocaleDateString('default', { month: 'short', year: 'numeric' })}
              </div>
              <button onClick={handleNextMonth} className="p-3 bg-white shadow-sm rounded-lg text-slate-600 hover:text-blue-600 active:scale-95 transition-all" aria-label="Next Month">
                <ChevronRight size={20} />
              </button>
            </div>
          </div>
        </header>

        <section className="grid grid-cols-1 md:grid-cols-3 gap-4">
          <div className="bg-white p-5 rounded-2xl shadow-sm border border-slate-100 relative overflow-hidden group">
            <div className="flex justify-between items-start mb-1">
              <label className="text-xs font-bold uppercase tracking-wider text-slate-400">Goal (Hrs)</label>
              {!isEditingGoal && (
                <button onClick={() => setIsEditingGoal(true)} className="p-2 -mr-2 -mt-2 text-slate-300 hover:text-blue-500 transition-colors">
                  <Edit2 size={16} />
                </button>
              )}
            </div>
            {isEditingGoal ? (
              <div className="flex items-center gap-2 mt-1">
                <input type="number" step="0.5" min="0" inputMode="decimal" value={tempGoal} onChange={(e) => setTempGoal(e.target.value)} onFocus={(e) => e.target.select()} className="w-full text-3xl font-bold text-slate-800 bg-slate-50 border-b-2 border-blue-500 outline-none py-1 px-2 rounded-t" autoFocus />
                <button onClick={handleGoalSave} className="bg-blue-600 text-white p-3 rounded-xl shadow-lg shadow-blue-200 active:scale-95 transition-all">
                  <Save size={20} />
                </button>
              </div>
            ) : (
              <div className="flex items-baseline gap-1" onClick={() => setIsEditingGoal(true)}>
                <span className="text-4xl font-bold text-slate-800 tracking-tight">{monthData.goalHours || 0}</span>
                <span className="text-sm font-medium text-slate-400">hours target</span>
              </div>
            )}
          </div>

          <div className="bg-blue-600 p-5 rounded-2xl shadow-lg shadow-blue-200 text-white md:col-span-2 relative overflow-hidden flex flex-col justify-between">
            <div className="absolute top-0 right-0 p-4 opacity-10 pointer-events-none"><Clock size={120} /></div>
            <div className="flex justify-between items-end relative z-10 mb-4">
              <div>
                <div className="text-blue-100 text-xs font-bold uppercase tracking-wider mb-1">Total Worked</div>
                <div className="text-4xl font-bold tracking-tight">{formatTime(totalMinutesWorked)}</div>
              </div>
              <div className="text-right">
                <div className="text-blue-200 text-xs font-medium">Left to do</div>
                <div className="text-xl font-semibold">{formatTime(minutesLeft)}</div>
              </div>
            </div>
            <div className="relative z-10">
              <div className="flex justify-between text-xs font-medium text-blue-100 mb-1.5">
                <span>Progress {savePending ? '(saving...)' : ''}</span>
                <span>{percentage}%</span>
              </div>
              <div className="w-full bg-black/20 rounded-full h-3 overflow-hidden backdrop-blur-sm">
                <div className="h-full bg-white/90 transition-all duration-700 ease-out rounded-full" style={{ width: `${percentage}%` }} />
              </div>
            </div>
          </div>
        </section>

        <div className="bg-white rounded-2xl shadow-sm border border-slate-200 overflow-hidden">
          <div className="grid grid-cols-7 bg-slate-50 border-b border-slate-200">
            {['S', 'M', 'T', 'W', 'T', 'F', 'S'].map((day, i) => (
              <div key={i} className="py-3 text-center text-xs font-bold text-slate-400">
                <span className="md:hidden">{day}</span>
                <span className="hidden md:inline">{['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'][i]}</span>
              </div>
            ))}
          </div>
          <div className="grid grid-cols-7 divide-y divide-slate-100 border-b border-slate-100 md:border-none">
            {Array.from({ length: new Date(year, month, 1).getDay() }).map((_, i) => (
              <div key={`empty-${i}`} className="bg-slate-50/30 h-24 md:h-32 hidden md:block" />
            ))}
            {Array.from({ length: startDay }).map((_, i) => (
              <div key={`empty-mob-${i}`} className="md:hidden bg-slate-50/30" />
            ))}
            {Array.from({ length: daysInMonth }).map((_, i) => {
              const day = i + 1;
              const dateKey = `${monthKey}-${String(day).padStart(2, '0')}`;
              const minutes = monthData.logs[dateKey] || 0;
              const isToday = new Date().getDate() === day && new Date().getMonth() === month && new Date().getFullYear() === year;
              return (
                <DayCell key={dateKey} day={day} isToday={isToday} minutes={minutes} onSave={(m) => handleLogUpdate(day, m)} />
              );
            })}
            {Array.from({ length: (7 - ((startDay + daysInMonth) % 7)) % 7 }).map((_, i) => (
              <div key={`end-${i}`} className="bg-slate-50/30 hidden md:block" />
            ))}
            {Array.from({ length: (7 - ((startDay + daysInMonth) % 7)) % 7 }).map((_, i) => (
              <div key={`end-mob-${i}`} className="md:hidden bg-slate-50/30" />
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

function DayCell({ day, isToday, minutes, onSave }) {
  const [isEditing, setIsEditing] = useState(false);
  const [h, setH] = useState(Math.floor(minutes / 60));
  const [m, setM] = useState(minutes % 60);
  const [showMinutes, setShowMinutes] = useState(false);

  useEffect(() => { setH(Math.floor(minutes / 60)); setM(minutes % 60); }, [minutes]);

  const handleSave = (e) => {
    e.stopPropagation();
    const total = (parseInt(h) || 0) * 60 + (parseInt(m) || 0);
    onSave(total);
    setIsEditing(false);
  };
  const handleCancel = (e) => {
    e.stopPropagation(); setH(Math.floor(minutes / 60)); setM(minutes % 60); setShowMinutes(false); setIsEditing(false);
  };
  const hasData = minutes > 0;

  return (
    <div onClick={() => !isEditing && setIsEditing(true)} className={`relative min-h-[100px] md:min-h-[140px] p-1 md:p-3 flex flex-col transition-all cursor-pointer border-r border-slate-100 last:border-r-0 ${isToday ? 'bg-blue-50 ring-2 ring-inset ring-blue-500 z-10' : 'bg-white active:bg-slate-50 hover:bg-slate-50'}`}>
      <div className="flex justify-between items-start mb-1">
        <span className={`text-xs md:text-sm font-bold flex items-center justify-center w-6 h-6 md:w-7 md:h-7 rounded-full ${isToday ? 'bg-blue-600 text-white shadow-md' : 'text-slate-400'}`}>{day}</span>
        {hasData && !isEditing && (
          <div className="md:flex hidden bg-green-100 text-green-700 text-[10px] font-bold px-2 py-0.5 rounded-full items-center"><Check size={10} className="mr-1" /> Done</div>
        )}
        {hasData && !isEditing && (<div className="md:hidden w-2 h-2 rounded-full bg-green-500"></div>)}
      </div>
      <div className="flex-1 flex flex-col justify-center items-center w-full">
        {isEditing ? (
          <div className="w-full flex flex-col gap-2 duration-200 z-20 absolute inset-0 bg-white/95 backdrop-blur-sm p-2 md:p-3 justify-center shadow-lg">
            <div className="flex items-center gap-2">
              <input type="number" inputMode="numeric" className="w-full text-center bg-slate-100 border-none rounded p-2 text-sm font-bold focus:ring-2 focus:ring-blue-500 outline-none" placeholder="Hours" value={h} onClick={(e) => e.stopPropagation()} onChange={e => setH(e.target.value)} onFocus={(e) => e.target.select()} autoFocus />
            </div>
            {!showMinutes ? (
              <button onClick={(e)=>{e.stopPropagation(); setShowMinutes(true);}} className="text-[10px] text-blue-600 hover:underline self-center">Add minutes</button>
            ) : (
              <div className="flex items-center gap-2">
                <input type="number" inputMode="numeric" className="w-full text-center bg-slate-100 border-none rounded p-2 text-sm font-bold focus:ring-2 focus:ring-blue-500 outline-none" placeholder="Minutes" value={m} onClick={(e) => e.stopPropagation()} onChange={e => setM(e.target.value)} onFocus={(e) => e.target.select()} />
              </div>
            )}
            <div className="flex gap-1">
              <button onClick={handleCancel} className="flex-1 flex items-center justify-center bg-slate-200 hover:bg-slate-300 text-slate-600 text-[10px] md:text-xs py-1.5 rounded"><X size={12} /></button>
              <button onClick={handleSave} className="flex-[2] flex items-center justify-center bg-blue-600 hover:bg-blue-700 text-white text-[10px] md:text-xs py-1.5 rounded shadow-sm"><Save size={12} className="mr-1" /> Save</button>
            </div>
          </div>
        ) : (
          <div className="group w-full h-full flex items-center justify-center">
            {hasData ? (
              <div className="text-center">
                <span className="text-sm md:text-xl font-bold text-slate-700 block leading-tight">{formatTime(minutes)}</span>
                <span className="text-[10px] text-slate-400 hidden md:inline">recorded</span>
              </div>
            ) : (
              <div className="flex flex-col items-center justify-center text-slate-300">
                <div className="md:hidden w-8 h-8 rounded-full bg-slate-50 flex items-center justify-center"><span className="text-xl leading-none text-slate-400 font-light">+</span></div>
                <div className="hidden md:flex flex-col items-center group-hover:text-blue-500 transition-colors"><Clock size={20} className="mb-1 opacity-50" /><span className="text-xs font-medium">Add</span></div>
              </div>
            )}
          </div>
        )}
      </div>
    </div>
  );
}

function AuthView({ onLogin, onRegister }) {
  const [mode, setMode] = useState('login'); // 'login' | 'register'
  const [username, setUsername] = useState('');
  const [password, setPassword] = useState('');
  const [error, setError] = useState('');
  const [loading, setLoading] = useState(false);

  const submit = async (e) => {
    e.preventDefault();
    setError('');
    setLoading(true);
    try {
      if (mode === 'login') await onLogin(username, password);
      else await onRegister(username, password);
    } catch (e) {
      setError(e.message || 'Request failed');
    } finally {
      setLoading(false);
    }
  };

  return (
    <div className="min-h-screen flex items-center justify-center p-6">
      <div className="w-full max-w-sm bg-white rounded-2xl shadow border border-slate-100 p-6 space-y-4">
        <div className="flex items-center gap-3">
          <div className="p-2.5 bg-blue-600 rounded-xl text-white shadow-blue-200 shadow-md"><CalendarIcon size={20} /></div>
          <div>
            <h1 className="text-xl font-bold text-slate-900 leading-none">Work Tracker</h1>
            <p className="text-xs text-slate-500 font-medium mt-1">{mode === 'login' ? 'Sign in' : 'Create account'}</p>
          </div>
        </div>
        {error && <div className="text-sm text-red-600 bg-red-50 border border-red-100 px-3 py-2 rounded">{error}</div>}
        <form className="space-y-3" onSubmit={submit}>
          <div className="space-y-1">
            <label className="text-xs font-bold uppercase tracking-wider text-slate-500">Username</label>
            <input className="w-full border rounded px-3 py-2 outline-none focus:ring-2 focus:ring-blue-500" value={username} onChange={(e)=>setUsername(e.target.value)} autoFocus />
          </div>
          <div className="space-y-1">
            <label className="text-xs font-bold uppercase tracking-wider text-slate-500">Password</label>
            <input type="password" className="w-full border rounded px-3 py-2 outline-none focus:ring-2 focus:ring-blue-500" value={password} onChange={(e)=>setPassword(e.target.value)} />
          </div>
          <button disabled={loading} className="w-full bg-blue-600 text-white rounded py-2.5 hover:bg-blue-700 disabled:opacity-60">{loading ? 'Please wait…' : (mode === 'login' ? 'Sign in' : 'Create account')}</button>
        </form>
        <div className="text-xs text-slate-500">
          {mode === 'login' ? (
            <span>No account? <button className="text-blue-600 hover:underline" onClick={()=>setMode('register')}>Register</button></span>
          ) : (
            <span>Already have an account? <button className="text-blue-600 hover:underline" onClick={()=>setMode('login')}>Sign in</button></span>
          )}
        </div>
      </div>
    </div>
  );
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);
