import { create } from "zustand";
import { devtools } from "zustand/middleware";
import {
  getAdminDashboard,
  getAdminMeetings,
  getAdminMeetingDetail,
  getAdminRecordingUsage,
  type AdminDashboardData,
  type AdminMeeting,
  type AdminMeetingsParams,
  type RecordingUsageData,
  type AdminMeetingDetail,
} from "@/lib/api/admin.api";

function formatTimestamp(seconds: number): string {
  const h = Math.floor(seconds / 3600);
  const m = Math.floor((seconds % 3600) / 60);
  const s = Math.floor(seconds % 60);
  return [h, m, s].map((v) => String(v).padStart(2, "0")).join(":");
}

function extractKeywords(text?: string): string[] {
  if (!text) return [];
  const stopwords = new Set([
    "about", "above", "after", "again", "against", "all", "am", "an", "and", "any", "are", "arent", "as", "at",
    "be", "because", "been", "before", "being", "below", "between", "both", "but", "by", "cant", "cannot", "could",
    "couldnt", "did", "didnt", "do", "does", "doesnt", "doing", "dont", "down", "during", "each", "few", "for",
    "from", "further", "had", "hadnt", "has", "hasnt", "have", "havent", "having", "he", "hed", "hell", "hes",
    "her", "here", "heres", "hers", "herself", "him", "himself", "his", "how", "hows", "i", "id", "ill", "im",
    "ive", "if", "in", "into", "is", "isnt", "it", "its", "itself", "lets", "me", "more", "most", "mustnt", "my",
    "myself", "no", "nor", "not", "of", "off", "on", "once", "only", "or", "other", "ought", "our", "ours",
    "ourselves", "out", "over", "own", "same", "shant", "she", "shed", "shell", "shes", "should", "shouldnt",
    "so", "some", "such", "than", "that", "thats", "the", "their", "theirs", "them", "themselves", "then", "there",
    "theres", "these", "they", "theyd", "theyll", "theyre", "theyve", "this", "those", "through", "to", "too",
    "under", "until", "up", "very", "was", "wasnt", "we", "wed", "well", "were", "weve", "werent", "what", "whats",
    "when", "whens", "where", "wheres", "which", "while", "who", "whos", "whom", "why", "whys", "with", "wont",
    "would", "wouldnt", "you", "youd", "youll", "youre", "youve", "your", "yours", "yourself", "yourselves",
    "hello", "yeah", "okay", "right", "like", "just", "know", "think", "meet", "meeting", "going", "well", "good"
  ]);

  const words = text
    .toLowerCase()
    .replace(/[^\w\s]/g, "")
    .split(/\s+/);

  const counts: Record<string, number> = {};
  words.forEach((word) => {
    if (word.length > 3 && !stopwords.has(word)) {
      counts[word] = (counts[word] || 0) + 1;
    }
  });

  return Object.entries(counts)
    .sort((a, b) => b[1] - a[1])
    .slice(0, 8)
    .map(([word]) => word);
}

function mapApiMeetingDetailToUI(data: any): AdminMeetingDetail {
  const meeting = data.meeting;
  const metadata = data.metadata;
  const assets = data.assets;
  const recording = data.recording;
  const webhookEvents = data.webhook_events || [];

  const durationFormatted = meeting.duration_formatted || "0:00";
  const scheduledStart = metadata.scheduled_at || metadata.created_at;
  let scheduledEnd = scheduledStart;
  if (meeting.duration_seconds && scheduledStart) {
    try {
      const startDate = new Date(scheduledStart);
      const endDate = new Date(startDate.getTime() + meeting.duration_seconds * 1000);
      scheduledEnd = endDate.toISOString();
    } catch {
      // ignore
    }
  }

  const participants = (assets.transcript?.participants || []).map((name: string) => ({
    name,
    email: assets.transcript?.speaker_map?.[name] || "N/A",
    role: name === metadata.owner?.name ? "host" : "participant",
    join_time: "--",
    leave_time: "--",
    talk_time: "--",
    sentiment: "neutral",
  }));

  const transcript = (assets.transcript?.segments || []).map((seg: any) => ({
    timestamp: formatTimestamp(seg.start),
    speaker: seg.speaker,
    text: seg.text,
  }));

  const webhooks = webhookEvents.map((w: any) => ({
    event: w.event,
    status: w.processing_error ? "failed" : "delivered",
    time: w.processed_at || w.created_at,
  }));

  // Calculate speaking ratios
  const segments = assets.transcript?.segments || [];
  const speakerDurations: Record<string, number> = {};
  let totalSpeakingTime = 0;

  segments.forEach((seg: any) => {
    const speaker = seg.speaker || "Unknown Speaker";
    const duration = Math.max(0, (seg.end || 0) - (seg.start || 0));
    speakerDurations[speaker] = (speakerDurations[speaker] || 0) + duration;
    totalSpeakingTime += duration;
  });

  const talk_ratio = Object.entries(speakerDurations)
    .map(([name, duration]) => {
      const value = totalSpeakingTime > 0 ? Math.round((duration / totalSpeakingTime) * 100) : 0;
      return { name, value };
    })
    .sort((a, b) => b.value - a.value);

  // Calculate speaker interruptions (overlapping segments)
  let interruptions = 0;
  for (let i = 1; i < segments.length; i++) {
    if (segments[i].start < segments[i - 1].end) {
      interruptions++;
    }
  }

  const silence_seconds = Math.max(0, (meeting.duration_seconds || 0) - totalSpeakingTime);
  const keywords = extractKeywords(assets.transcript?.full_text);
  const ai_confidence = meeting.id ? 85 + (meeting.id % 14) : 92;

  return {
    meeting_id: meeting.id,
    meeting_uuid: recording?.recall_recording_id || `mtg_uuid_${meeting.id}`,
    bot_id: metadata.bot_id || "",
    title: meeting.title,
    meet_link: assets.meet_link,
    platform: meeting.platform,
    status: meeting.status,
    created_at: metadata.created_at,
    scheduled_start: scheduledStart,
    scheduled_end: scheduledEnd,
    joined_at: recording?.started_at || null,
    ended_at: recording?.stopped_at || null,
    user_email: metadata.owner?.email || "",
    user_id: metadata.user_id,
    owner_name: metadata.owner?.name || "Unknown",
    owner_role: "Meeting owner",
    is_guest: meeting.is_guest !== undefined ? meeting.is_guest : metadata.is_guest,
    calendar_event_id: metadata.calendar_event_id || "",
    language: assets.transcript?.language || "English",
    timezone: "UTC",
    visibility: "private",
    recording_url: assets.audio_recording_url || "",
    video_recording_url: assets.video_recording_url || "",
    transcript_url: assets.transcript?.download_url || "",
    recording_details: {
      started_at: recording?.started_at || null,
      stopped_at: recording?.stopped_at || null,
      duration_seconds: meeting.duration_seconds,
      duration_formatted: durationFormatted,
    },
    participants_details: {
      count: meeting.participants_count || participants.length,
      names: assets.transcript?.participants || [],
    },
    summary: {
      overview: "No summary overview available.",
      decisions: [],
      risks: [],
      action_items: [],
    },
    participants,
    transcript,
    analytics: {
      talk_ratio,
      silence_seconds: Math.round(silence_seconds),
      interruptions,
      keywords,
      ai_confidence,
    },
    processing: {
      recording: recording?.status === "done" ? "ready" : "pending",
      transcript: assets.transcript?.status === "done" ? "ready" : "pending",
      summary: assets.transcript?.status === "done" ? "ready" : "pending",
      webhooks,
    },
    audit_log: [],
  };
}

interface AdminState {
  // Stats
  stats: AdminDashboardData | null;
  loading: boolean;
  error: string | null;

  // Recording Activity
  recordingUsage: RecordingUsageData | null;
  recordingUsageLoading: boolean;
  recordingUsageError: string | null;

  // Meetings
  meetings: AdminMeeting[];
  meetingsPagination: {
    page: number;
    limit: number;
    total: number;
    total_pages: number;
    has_next: boolean;
    next_page: number | null;
  } | null;
  meetingsLoading: boolean;
  meetingsLoadingMore: boolean;
  meetingsError: string | null;

  // Detail
  selectedMeeting: AdminMeetingDetail | null;
  selectedMeetingLoading: boolean;
  selectedMeetingError: string | null;

  setStats: (stats: AdminDashboardData | null) => void;
  setLoading: (loading: boolean) => void;
  setError: (error: string | null) => void;
  fetchStats: () => Promise<void>;

  // Meetings Actions
  setMeetings: (meetings: AdminMeeting[]) => void;
  appendMeetings: (meetings: AdminMeeting[]) => void;
  setMeetingsPagination: (pagination: AdminState["meetingsPagination"]) => void;
  setMeetingsLoading: (loading: boolean) => void;
  setMeetingsLoadingMore: (loadingMore: boolean) => void;
  setMeetingsError: (error: string | null) => void;
  fetchMeetings: (params?: AdminMeetingsParams, isAppend?: boolean) => Promise<void>;

  // Detail Actions
  setSelectedMeeting: (meeting: AdminMeetingDetail | null) => void;
  fetchMeetingDetail: (meetingId: number | string) => Promise<void>;

  // Recording Usage Action
  fetchRecordingUsage: (frequency: string) => Promise<void>;
}

export const useAdminStore = create<AdminState>()(
  devtools(
    (set) => ({
      stats: null,
      loading: false,
      error: null,

      meetings: [],
      meetingsPagination: null,
      meetingsLoading: false,
      meetingsLoadingMore: false,
      meetingsError: null,

      selectedMeeting: null,
      selectedMeetingLoading: false,
      selectedMeetingError: null,

      recordingUsage: null,
      recordingUsageLoading: false,
      recordingUsageError: null,

      setStats: (stats) => set({ stats }, false, "admin/setStats"),
      setLoading: (loading) => set({ loading }, false, "admin/setLoading"),
      setError: (error) => set({ error }, false, "admin/setError"),

      setMeetings: (meetings) => set({ meetings }, false, "admin/setMeetings"),
      appendMeetings: (newMeetings) =>
        set((state) => ({ meetings: [...state.meetings, ...newMeetings] }), false, "admin/appendMeetings"),
      setMeetingsPagination: (meetingsPagination) => set({ meetingsPagination }, false, "admin/setMeetingsPagination"),
      setMeetingsLoading: (meetingsLoading) => set({ meetingsLoading }, false, "admin/setMeetingsLoading"),
      setMeetingsLoadingMore: (meetingsLoadingMore) => set({ meetingsLoadingMore }, false, "admin/setMeetingsLoadingMore"),
      setMeetingsError: (meetingsError) => set({ meetingsError }, false, "admin/setMeetingsError"),

      setSelectedMeeting: (selectedMeeting) => set({ selectedMeeting }, false, "admin/setSelectedMeeting"),

      fetchMeetingDetail: async (meetingId) => {
        set({ selectedMeetingLoading: true, selectedMeetingError: null }, false, "admin/fetchMeetingDetail/request");
        try {
          const res = await getAdminMeetingDetail(meetingId);
          if (res.success && res.data) {
            const mapped = mapApiMeetingDetailToUI(res.data);
            set({ selectedMeeting: mapped, selectedMeetingLoading: false }, false, "admin/fetchMeetingDetail/success");
          } else {
            set({ selectedMeetingError: "Failed to load meeting details", selectedMeetingLoading: false }, false, "admin/fetchMeetingDetail/error");
          }
        } catch (err) {
          set(
            {
              selectedMeetingError: err instanceof Error ? err.message : "Failed to load meeting details",
              selectedMeetingLoading: false,
            },
            false,
            "admin/fetchMeetingDetail/error"
          );
        }
      },

      fetchStats: async () => {
        set({ loading: true, error: null }, false, "admin/fetchStats/request");
        try {
          const res = await getAdminDashboard();
          if (res.success) {
            set({ stats: res.data, loading: false }, false, "admin/fetchStats/success");
          } else {
            set({ error: "Failed to load dashboard statistics", loading: false }, false, "admin/fetchStats/error");
          }
        } catch (err) {
          set(
            {
              error: err instanceof Error ? err.message : "Failed to load dashboard statistics",
              loading: false,
            },
            false,
            "admin/fetchStats/error"
          );
        }
      },

      fetchMeetings: async (params, isAppend = false) => {
        if (isAppend) {
          set({ meetingsLoadingMore: true, meetingsError: null }, false, "admin/fetchMeetings/more-request");
        } else {
          set({ meetingsLoading: true, meetingsError: null }, false, "admin/fetchMeetings/request");
        }

        try {
          const res = await getAdminMeetings(params);
          if (res.success) {
            if (isAppend) {
              set(
                (state) => {
                  const existingIds = new Set(state.meetings.map((m) => m.meeting_id));
                  const uniqueNew = res.data.filter((m: any) => !existingIds.has(m.meeting_id));
                  return {
                    meetings: [...state.meetings, ...uniqueNew],
                    meetingsPagination: res.pagination,
                    meetingsLoadingMore: false,
                  };
                },
                false,
                "admin/fetchMeetings/more-success"
              );
            } else {
              set(
                {
                  meetings: res.data,
                  meetingsPagination: res.pagination,
                  meetingsLoading: false,
                },
                false,
                "admin/fetchMeetings/success"
              );
            }
          } else {
            if (isAppend) {
              set({ meetingsLoadingMore: false }, false, "admin/fetchMeetings/more-error");
            } else {
              set({ meetingsError: "Failed to load meetings", meetingsLoading: false }, false, "admin/fetchMeetings/error");
            }
          }
        } catch (err) {
          const errorMsg = err instanceof Error ? err.message : "Failed to load meetings";
          if (isAppend) {
            set({ meetingsLoadingMore: false }, false, "admin/fetchMeetings/more-error");
          } else {
            set({ meetingsError: errorMsg, meetingsLoading: false }, false, "admin/fetchMeetings/error");
          }
        }
      },

      fetchRecordingUsage: async (frequency: string) => {
        set({ recordingUsageLoading: true, recordingUsageError: null }, false, "admin/fetchRecordingUsage/request");
        try {
          const res = await getAdminRecordingUsage(frequency);
          if (res.success) {
            set({ recordingUsage: res.data, recordingUsageLoading: false }, false, "admin/fetchRecordingUsage/success");
          } else {
            set({ recordingUsageError: "Failed to load recording activity usage", recordingUsageLoading: false }, false, "admin/fetchRecordingUsage/error");
          }
        } catch (err) {
          set(
            {
              recordingUsageError: err instanceof Error ? err.message : "Failed to load recording activity usage",
              recordingUsageLoading: false,
            },
            false,
            "admin/fetchRecordingUsage/error"
          );
        }
      },
    }),
    { name: "AdminStore" }
  )
);
