'use client';

import { use, useEffect, useState } from 'react';
import Link from 'next/link';
import { toast } from 'sonner';
import { EngagementPeriodChips, type EngagementPeriod } from '@/components/mobile/EngagementPeriodChips';
import { EngagementProfileSkeleton } from '@/components/mobile/EngagementProfileSkeleton';
import { EngagementProfileHeader } from '@/components/mobile/EngagementProfileHeader';
import { EngagementProfileMetricGrid } from '@/components/mobile/EngagementProfileMetricGrid';
import { EngagementProfileBreakdown } from '@/components/mobile/EngagementProfileBreakdown';
import { EngagementRecentEntries } from '@/components/mobile/EngagementRecentEntries';
import { EngagementRecentMeetings } from '@/components/mobile/EngagementRecentMeetings';

interface ApiResponse {
  user: {
    id: string;
    displayName: string;
    email: string;
    jobTitle: string | null;
    department: string | null;
    accountEnabled: boolean | null;
    autotaskResourceId: number | null;
  };
  afterHours: { messages: number; meetings: number; messagesPct: number; meetingsPct: number };
  snapshots: Array<{
    period_type: string;
    period_end: string;                                    // verified present — migration 041 line 18
    teams_chat_messages: number | null;
    teams_private_messages: number | null;
    emails_sent: number | null;
    teams_meetings_attended: number | null;
    teams_meetings_organized: number | null;
    meeting_duration_seconds: number | null;
    after_hours_messages: number | null;
  }>;
  hours: {
    d7:  { total: number; billable: number };
    d30: { total: number; billable: number };
    d90: { total: number; billable: number };
  } | null;
  recentEntries: Array<{
    entry_date: string;
    hours_worked: number;
    billable: boolean | null;
    notes: string | null;
    title: string | null;
    start_date_time: string | null;
    end_date_time: string | null;
    company_name: string | null;
  }>;
  recentTeamsMeetings: Array<{
    subject: string | null;
    startTime: string;
    durationMinutes: number | null;
    attendeeCount: number;
    clientAttendeeCount: number;
    hasClientAttendees: boolean;
    clientCompanies: string[];
    participantNames: string[];
    matchedEntries: Array<{
      hours_worked: number;
      billable: boolean | null;
      notes: string | null;
      title: string | null;
      company_name: string | null;
      start_date_time: string | null;
      end_date_time: string | null;
    }>;
  }>;
  zoom: { calls: { d7: { total: number }; d30: { total: number }; d90: { total: number } } } | null;
}

export default function MobileEngagementUserProfilePage({
  params,
}: {
  params: Promise<{ userId: string }>;
}) {
  // D-04: rely on App Router default scrollRestoration
  const { userId } = use(params);   // Next.js 16: params is a Promise — unwrap with React.use

  const [period, setPeriod] = useState<EngagementPeriod>('D30');  // D-09
  const [data, setData] = useState<ApiResponse | null>(null);
  const [loading, setLoading] = useState<boolean>(true);
  const [errorState, setErrorState] = useState<'none' | 'not-found' | 'failed'>('none');
  // retryNonce: incrementing this re-runs the fetch effect without changing `period`.
  // Used by the Retry button in the failed-state branch (issue-7 fix).
  const [retryNonce, setRetryNonce] = useState<number>(0);

  useEffect(() => {
    let cancelled = false;
    setLoading(true);
    setErrorState('none');
    fetch(`/api/engagement/user/${encodeURIComponent(userId)}?period=${period}`)
      .then(async (res) => {
        if (cancelled) return;
        if (res.status === 404) {
          setErrorState('not-found');
          setData(null);
          return;
        }
        if (!res.ok) {
          throw new Error(`HTTP ${res.status}`);
        }
        const json = (await res.json()) as ApiResponse;
        setData(json);
      })
      .catch((err) => {
        if (cancelled) return;
        console.error('[mobile/engagement/profile] fetch failed', err);
        setErrorState('failed');
        toast.error('Failed to load profile — tap to retry');
      })
      .finally(() => {
        if (!cancelled) setLoading(false);
      });
    return () => { cancelled = true; };
  }, [userId, period, retryNonce]);

  // ── Error: 404 ──────────────────────────────────────────────────────
  if (errorState === 'not-found') {
    return (
      <main className="px-4 pb-safe">
        <div className="py-12 text-center space-y-3">
          <h1 className="text-xl font-semibold">User not found</h1>
          <p className="text-sm text-muted-foreground">This profile is no longer available.</p>
          <Link href="/mobile/engagement" className="text-sm text-primary underline-offset-4 hover:underline inline-block min-h-[44px] py-3">
            Back to Engagement
          </Link>
        </div>
      </main>
    );
  }

  // ── Error: 500/network — show skeleton + Retry ──────────────────────
  if (errorState === 'failed' && !data) {
    return (
      <main className="px-4 pb-safe">
        <EngagementPeriodChips period={period} onPeriodChange={setPeriod} />
        <EngagementProfileSkeleton />
        <button
          type="button"
          className="mt-4 inline-flex items-center justify-center min-h-[44px] px-4 py-2 rounded-md bg-primary text-primary-foreground text-sm font-semibold"
          onClick={() => setRetryNonce((n) => n + 1)}
        >
          Retry
        </button>
      </main>
    );
  }

  // Helper to derive period-scoped values once data is loaded.
  const periodKey = period === 'D7' ? 'd7' : period === 'D90' ? 'd90' : 'd30';
  const hoursForPeriod  = data?.hours?.[periodKey]?.total ?? 0;
  const billableForPeriod = data?.hours?.[periodKey]?.billable ?? 0;
  const daysWorkedForPeriod = data
    ? new Set(data.recentEntries.map((e) => String(e.entry_date).slice(0, 10))).size
    : 0;
  const snapshotForPeriod = data?.snapshots.find((s) => s.period_type === period) ?? null;
  const meetingsAttended = snapshotForPeriod?.teams_meetings_attended ?? 0;

  // Last-active derivation for the header (D-06):
  // most recent of (recentEntries[0].entry_date, latest snapshot.period_end).
  // If `period_end` ever turns out to be missing from the API at runtime, fall
  // back to recentEntries[0].entry_date alone (executor can simplify this block
  // — see <discovery> above).
  let lastActiveAt: string | null = null;
  if (data) {
    const candidates: number[] = [];
    if (data.recentEntries[0]) candidates.push(new Date(data.recentEntries[0].entry_date).getTime());
    const latestSnapshot = data.snapshots
      .filter((s) => s.period_end)
      .map((s) => new Date(s.period_end).getTime())
      .filter((n) => Number.isFinite(n))
      .sort((a, b) => b - a)[0];
    if (latestSnapshot) candidates.push(latestSnapshot);
    if (candidates.length > 0) {
      lastActiveAt = new Date(Math.max(...candidates)).toISOString();
    }
  }

  return (
    <main className="px-4 pb-safe">
      <h1 className="text-xl font-semibold pt-4 pb-2">
        {data?.user.displayName ?? ' '}
      </h1>
      <EngagementPeriodChips period={period} onPeriodChange={setPeriod} />

      <div className="space-y-4">
        {loading || !data ? (
          <EngagementProfileSkeleton />
        ) : (
          <>
            <EngagementProfileHeader
              displayName={data.user.displayName}
              email={data.user.email}
              jobTitle={data.user.jobTitle}
              department={data.user.department}
              lastActiveAt={lastActiveAt}
              userId={userId}
            />
            <EngagementProfileMetricGrid
              hoursWorked={hoursForPeriod}
              billableHours={billableForPeriod}
              daysWorked={daysWorkedForPeriod}
              meetingsAttended={Number(meetingsAttended)}
            />
            <EngagementProfileBreakdown
              hoursWorked={hoursForPeriod}
              billableHours={billableForPeriod}
              daysWorked={daysWorkedForPeriod}
              teamsMessages={
                Number(snapshotForPeriod?.teams_chat_messages ?? 0) +
                Number(snapshotForPeriod?.teams_private_messages ?? 0)
              }
              emailsSent={Number(snapshotForPeriod?.emails_sent ?? 0)}
              afterHoursMessagesPct={data.afterHours.messagesPct}
              afterHoursMeetingsPct={data.afterHours.meetingsPct}
              meetingsAttended={Number(snapshotForPeriod?.teams_meetings_attended ?? 0)}
              meetingsOrganized={Number(snapshotForPeriod?.teams_meetings_organized ?? 0)}
              meetingDurationSeconds={Number(snapshotForPeriod?.meeting_duration_seconds ?? 0)}
              zoomCalls={data.zoom ? Number(data.zoom.calls[periodKey].total) : null}
            />
            <EngagementRecentEntries entries={data.recentEntries} />
            <EngagementRecentMeetings meetings={data.recentTeamsMeetings} />
          </>
        )}
      </div>
    </main>
  );
}
