import { createSlice, createAsyncThunk, PayloadAction } from "@reduxjs/toolkit";

export interface AdminUser {
  id: string;
  email: string;
  display_name: string;
  role: "super_admin" | "client_admin" | "user";
  is_active: boolean;
  last_login_at: string | null;
  created_at: string | null;
}

export interface AdminClient {
  id: string;
  name: string;
  slug: string;
  logo_path: string | null;
  retention_days: number | null;
  review_policy: string;
  is_active: boolean;
  created_at: string | null;
}

export interface AdminTeam {
  id: string;
  name: string;
  client_id: string | null;
  is_default: boolean;
  created_at: string | null;
  members?: AdminUser[];
}

export interface AuditLogEntry {
  id: string;
  user_id: string | null;
  action: string;
  resource_type: string;
  resource_id: string | null;
  client_id: string | null;
  details: Record<string, unknown> | null;
  ip_address: string | null;
  created_at: string | null;
}

export interface BrandConfig {
  id: string;
  client_id: string;
  primary_colors: string[] | null;
  secondary_colors: string[] | null;
  fonts: Record<string, string> | null;
  logo_paths: string[] | null;
  voice_rules: string | null;
  voice_examples: Array<{ good: string; bad: string }> | null;
  guideline_doc_path: string | null;
}

export interface MasterDeck {
  id: string;
  client_id: string;
  name: string;
  description: string | null;
  thumbnail_path: string | null;
  parse_mode: string;
  parse_status: string;
  is_active: boolean;
  layouts: Array<Record<string, unknown>> | null;
  created_at: string | null;
}

interface AdminState {
  users: AdminUser[];
  clients: AdminClient[];
  teams: AdminTeam[];
  auditLogs: AuditLogEntry[];
  brandConfig: BrandConfig | null;
  masterDecks: MasterDeck[];
  isLoading: boolean;
  error: string | null;
}

const initialState: AdminState = {
  users: [],
  clients: [],
  teams: [],
  auditLogs: [],
  brandConfig: null,
  masterDecks: [],
  isLoading: false,
  error: null,
};

// --- Users ---

export const fetchUsers = createAsyncThunk(
  "admin/fetchUsers",
  async (_, { rejectWithValue }) => {
    const res = await fetch("/api/v1/admin/users");
    if (!res.ok) return rejectWithValue("Failed to fetch users");
    return await res.json();
  }
);

export const updateUserRole = createAsyncThunk(
  "admin/updateUserRole",
  async ({ userId, role }: { userId: string; role: string }, { rejectWithValue }) => {
    const res = await fetch(`/api/v1/admin/users/${userId}/role?role=${role}`, { method: "PUT" });
    if (!res.ok) return rejectWithValue("Failed to update role");
    return await res.json();
  }
);

export const deactivateUser = createAsyncThunk(
  "admin/deactivateUser",
  async (userId: string, { rejectWithValue }) => {
    const res = await fetch(`/api/v1/admin/users/${userId}`, { method: "DELETE" });
    if (!res.ok) return rejectWithValue("Failed to deactivate user");
    return userId;
  }
);

// --- Clients ---

export const fetchClients = createAsyncThunk(
  "admin/fetchClients",
  async (_, { rejectWithValue }) => {
    const res = await fetch("/api/v1/admin/clients");
    if (!res.ok) return rejectWithValue("Failed to fetch clients");
    return await res.json();
  }
);

export const createClient = createAsyncThunk(
  "admin/createClient",
  async ({ name, review_policy }: { name: string; review_policy?: string }, { rejectWithValue }) => {
    const res = await fetch("/api/v1/admin/clients", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ name, review_policy: review_policy || "self_approve" }),
    });
    if (!res.ok) {
      const data = await res.json().catch(() => ({}));
      return rejectWithValue(data.detail || "Failed to create client");
    }
    return await res.json();
  }
);

// --- Teams ---

export const fetchTeams = createAsyncThunk(
  "admin/fetchTeams",
  async (clientId?: string) => {
    const url = clientId
      ? `/api/v1/admin/teams?client_id=${clientId}`
      : "/api/v1/admin/teams";
    const res = await fetch(url);
    if (!res.ok) throw new Error("Failed to fetch teams");
    return await res.json();
  }
);

export const fetchTeamDetail = createAsyncThunk(
  "admin/fetchTeamDetail",
  async (teamId: string) => {
    const res = await fetch(`/api/v1/admin/teams/${teamId}`);
    if (!res.ok) throw new Error("Failed to fetch team");
    return await res.json();
  }
);

export const addTeamMember = createAsyncThunk(
  "admin/addTeamMember",
  async ({ teamId, userId }: { teamId: string; userId: string }, { rejectWithValue }) => {
    const res = await fetch(`/api/v1/admin/teams/${teamId}/members`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ user_id: userId }),
    });
    if (!res.ok) {
      const data = await res.json().catch(() => ({}));
      return rejectWithValue(data.detail || "Failed to add member");
    }
    return await res.json();
  }
);

export const removeTeamMember = createAsyncThunk(
  "admin/removeTeamMember",
  async ({ teamId, userId }: { teamId: string; userId: string }, { rejectWithValue }) => {
    const res = await fetch(`/api/v1/admin/teams/${teamId}/members/${userId}`, { method: "DELETE" });
    if (!res.ok) return rejectWithValue("Failed to remove member");
    return { teamId, userId };
  }
);

// --- Audit Logs ---

export const fetchAuditLogs = createAsyncThunk(
  "admin/fetchAuditLogs",
  async (params?: Record<string, string>) => {
    const query = params ? "?" + new URLSearchParams(params).toString() : "";
    const res = await fetch(`/api/v1/admin/audit-log${query}`);
    if (!res.ok) throw new Error("Failed to fetch audit logs");
    return await res.json();
  }
);

// --- Brand Config ---

export const fetchBrandConfig = createAsyncThunk(
  "admin/fetchBrandConfig",
  async (clientId: string) => {
    const res = await fetch(`/api/v1/admin/clients/${clientId}/brand`);
    if (!res.ok) {
      if (res.status === 404) return null;
      throw new Error("Failed to fetch brand config");
    }
    return await res.json();
  }
);

export const updateBrandConfig = createAsyncThunk(
  "admin/updateBrandConfig",
  async ({ clientId, data }: { clientId: string; data: Partial<BrandConfig> }, { rejectWithValue }) => {
    const res = await fetch(`/api/v1/admin/clients/${clientId}/brand`, {
      method: "PUT",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(data),
    });
    if (!res.ok) return rejectWithValue("Failed to update brand config");
    return await res.json();
  }
);

// --- Master Decks ---

export const fetchMasterDecks = createAsyncThunk(
  "admin/fetchMasterDecks",
  async (clientId: string) => {
    const res = await fetch(`/api/v1/admin/clients/${clientId}/master-decks`);
    if (!res.ok) throw new Error("Failed to fetch master decks");
    return await res.json();
  }
);

export const uploadMasterDeck = createAsyncThunk(
  "admin/uploadMasterDeck",
  async ({ clientId, file }: { clientId: string; file: File }, { rejectWithValue }) => {
    const formData = new FormData();
    formData.append("file", file);
    const res = await fetch(`/api/v1/admin/clients/${clientId}/master-decks`, {
      method: "POST",
      body: formData,
    });
    if (!res.ok) {
      const data = await res.json().catch(() => ({}));
      return rejectWithValue(data.detail || "Failed to upload master deck");
    }
    return await res.json();
  }
);

export const fetchMasterDeckDetail = createAsyncThunk(
  "admin/fetchMasterDeckDetail",
  async (deckId: string) => {
    const res = await fetch(`/api/v1/admin/master-decks/${deckId}`);
    if (!res.ok) throw new Error("Failed to fetch master deck detail");
    return await res.json();
  }
);

export const updateMasterDeck = createAsyncThunk(
  "admin/updateMasterDeck",
  async ({ deckId, data }: { deckId: string; data: { name?: string; description?: string; is_active?: boolean } }, { rejectWithValue }) => {
    const res = await fetch(`/api/v1/admin/master-decks/${deckId}`, {
      method: "PUT",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(data),
    });
    if (!res.ok) return rejectWithValue("Failed to update master deck");
    return await res.json();
  }
);

export const updateMasterDeckLayout = createAsyncThunk(
  "admin/updateMasterDeckLayout",
  async (
    { deckId, layoutIndex, data }: { deckId: string; layoutIndex: number; data: { layout_name?: string; layout_type?: string; react_code?: string } },
    { rejectWithValue }
  ) => {
    const res = await fetch(`/api/v1/admin/master-decks/${deckId}/layouts/${layoutIndex}`, {
      method: "PUT",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(data),
    });
    if (!res.ok) return rejectWithValue("Failed to update layout");
    return await res.json();
  }
);

export const reparseMasterDeck = createAsyncThunk(
  "admin/reparseMasterDeck",
  async ({ deckId, parseMode }: { deckId: string; parseMode?: string }, { rejectWithValue }) => {
    const params = parseMode ? `?parse_mode=${parseMode}` : "";
    const res = await fetch(`/api/v1/admin/master-decks/${deckId}/reparse${params}`, { method: "POST" });
    if (!res.ok) {
      const data = await res.json().catch(() => ({}));
      return rejectWithValue(data.detail || "Failed to trigger reparse");
    }
    return await res.json();
  }
);

export const deleteMasterDeck = createAsyncThunk(
  "admin/deleteMasterDeck",
  async (deckId: string, { rejectWithValue }) => {
    const res = await fetch(`/api/v1/admin/master-decks/${deckId}`, { method: "DELETE" });
    if (!res.ok) return rejectWithValue("Failed to delete master deck");
    return deckId;
  }
);

export const deleteMasterDeckLayout = createAsyncThunk(
  "admin/deleteMasterDeckLayout",
  async ({ deckId, layoutIndex }: { deckId: string; layoutIndex: number }, { rejectWithValue }) => {
    const res = await fetch(`/api/v1/admin/master-decks/${deckId}/layouts/${layoutIndex}`, {
      method: "DELETE",
    });
    if (!res.ok) return rejectWithValue("Failed to delete layout");
    return { deckId, layoutIndex };
  }
);

export const bulkDeleteMasterDeckLayouts = createAsyncThunk(
  "admin/bulkDeleteMasterDeckLayouts",
  async ({ deckId, indices }: { deckId: string; indices: number[] }, { rejectWithValue }) => {
    const res = await fetch(`/api/v1/admin/master-decks/${deckId}/layouts/bulk-delete`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ indices }),
    });
    if (!res.ok) return rejectWithValue("Failed to delete layouts");
    return await res.json();
  }
);

const adminSlice = createSlice({
  name: "admin",
  initialState,
  reducers: {
    clearError: (state) => {
      state.error = null;
    },
  },
  extraReducers: (builder) => {
    // Users
    builder
      .addCase(fetchUsers.pending, (state) => { state.isLoading = true; state.error = null; })
      .addCase(fetchUsers.fulfilled, (state, action) => { state.users = action.payload; state.isLoading = false; })
      .addCase(fetchUsers.rejected, (state, action) => { state.isLoading = false; state.error = action.payload as string; })
      .addCase(deactivateUser.fulfilled, (state, action) => {
        state.users = state.users.map((u) => u.id === action.payload ? { ...u, is_active: false } : u);
      })
    // Clients
      .addCase(fetchClients.pending, (state) => { state.isLoading = true; state.error = null; })
      .addCase(fetchClients.fulfilled, (state, action) => { state.clients = action.payload; state.isLoading = false; })
      .addCase(fetchClients.rejected, (state, action) => { state.isLoading = false; state.error = action.payload as string; })
      .addCase(createClient.fulfilled, (state, action) => {
        state.clients.push(action.payload);
      })
    // Teams
      .addCase(fetchTeams.fulfilled, (state, action) => { state.teams = action.payload; })
    // Audit Logs
      .addCase(fetchAuditLogs.fulfilled, (state, action) => { state.auditLogs = action.payload; })
    // Brand Config
      .addCase(fetchBrandConfig.fulfilled, (state, action) => { state.brandConfig = action.payload; })
      .addCase(updateBrandConfig.fulfilled, (state, action) => { state.brandConfig = action.payload; })
    // Master Decks
      .addCase(fetchMasterDecks.fulfilled, (state, action) => { state.masterDecks = action.payload; })
      .addCase(uploadMasterDeck.fulfilled, (state, action) => {
        state.masterDecks.unshift(action.payload);
      })
      .addCase(deleteMasterDeck.fulfilled, (state, action) => {
        state.masterDecks = state.masterDecks.filter((d) => d.id !== action.payload);
      });
  },
});

export const { clearError } = adminSlice.actions;
export default adminSlice.reducer;
