import { Eventra } from "@duxcore/eventra";
import UserController from "../controllers/UserController";
import {
  SessionController,
  SessionTokensObject,
} from "../controllers/SessionController";
import { RoleController } from "../controllers/RoleController";
import { CompanyController } from "../controllers/CompanyController";
import { JsonWebTokenError } from "jsonwebtoken";
import { User, Company } from "../../generated/prisma/client";
import { DefaultEventsMap, Socket } from "socket.io";
import { WorkerQueue } from "./workers/queues";

export type JobLogLevel = "INFO" | "WARN" | "ERROR" | "DEBUG";

export interface EventTypes {
  // API Lifecycle
  "api:started": () => void;

  // User Events
  "user:created": (user: UserController) => void;
  "user:updated": (data: {
    user: UserController;
    updatedValues: Partial<User>;
  }) => void;
  "user:deleted": (data: { id: string }) => void;
  "user:authenticated": (data: {
    user: UserController;
    tokens: SessionTokensObject;
  }) => void;
  "user:role:assigned": (data: {
    user: UserController;
    role: RoleController;
  }) => void;
  "user:role:removed": (data: {
    user: UserController;
    role: RoleController;
  }) => void;

  // Session Events
  "session:created": (data: {
    user: UserController;
    session: SessionController;
  }) => void;
  "session:tokens_generated": (data: {
    session: SessionController;
    tokens: SessionTokensObject;
  }) => void;
  "session:token_refresh": (data: {
    session: SessionController;
    tokens: SessionTokensObject;
  }) => void;
  "session:invalidated": (session: SessionController) => void;
  "session:terminated": (session: SessionController) => void;

  // Role Events
  "role:created": (role: RoleController) => void;
  "role:deleted": (role: RoleController) => void;
  "role:updated": (data: {
    role: RoleController;
    updateData: Parameters<typeof RoleController.prototype.update>["0"];
  }) => void;
  "role:permissions:set": (data: {
    previous: string[];
    previousSigned: string;
    current: string[];
    currentSigned: string;
    role: RoleController;
  }) => void;
  "role:permissions:added": (data: {
    previous: string[];
    previousSigned: string;
    added: string[];
    currentSigned: string;
    role: RoleController;
  }) => void;
  "role:permissions:removed": (data: {
    previous: string[];
    previousSigned: string;
    removed: string[];
    currentSigned: string;
    role: RoleController;
  }) => void;
  "role:permissions:verification_error": (data: {
    currentSigned: string;
    attemptedVerification: string;
    err: Error;
    role: RoleController;
  }) => void;

  // Company Events
  "company:fetched": (company: CompanyController) => void;
  "company:refreshed_from_cw": (company: CompanyController) => void;
  "company:configurations_fetched": (data: {
    company: CompanyController;
    configurationCount: number;
  }) => void;

  // ConnectWise Integration Events
  "cw:companies:refresh:check": () => void;
  "cw:companies:refresh:started": () => void;
  "cw:companies:refresh:completed": (data: {
    internalCompaniesCount: number;
    externalCompaniesCount: number;
    companiesUpdated: number;
  }) => void;
  "cw:companies:refresh:skipped": (data: {
    internalCompaniesCount: number;
    externalCompaniesCount: number;
  }) => void;
  "cw:company:data:updated": (data: {
    company: CompanyController;
    updatedFields: Partial<Company>;
  }) => void;

  // ConnectWise Catalog Events
  "cw:catalog:refresh:check": () => void;
  "cw:catalog:refresh:started": (data: {
    totalCw: number;
    totalDb: number;
    staleCount: number;
  }) => void;
  "cw:catalog:refresh:completed": (data: {
    totalCw: number;
    totalDb: number;
    staleCount: number;
    itemsUpdated: number;
  }) => void;
  "cw:catalog:refresh:skipped": (data: {
    totalCw: number;
    totalDb: number;
    staleCount: number;
  }) => void;

  // UniFi Events
  "unifi:login:ok": (data: {
    type: "unifi-os" | "legacy";
    status: number;
  }) => void;
  "unifi:login:fallback": () => void;
  "unifi:reauth": () => void;
  "unifi:sites:sync:started": () => void;
  "unifi:sites:sync:completed": (data: {
    total: number;
    created: number;
    updated: number;
  }) => void;
  "unifi:wlan:fetched": (data: { path: string }) => void;
  "unifi:wlan:fetch_failed": (data: {
    path: string;
    status: number | unknown;
  }) => void;

  // ConnectWise Inventory Events
  "cw:inventory:refresh:check": () => void;
  "cw:inventory:refresh:started": (data: { totalItems: number }) => void;
  "cw:inventory:refresh:completed": (data: {
    totalItems: number;
    updatedCount: number;
  }) => void;
  "cw:inventory:refresh:skipped": (data: {
    totalItems: number;
    updatedCount: number;
  }) => void;

  // ConnectWise Opportunities Events
  "cw:opportunities:refresh:check": () => void;
  "cw:opportunities:refresh:started": (data: {
    totalCw: number;
    totalDb: number;
    staleCount: number;
  }) => void;
  "cw:opportunities:refresh:completed": (data: {
    totalCw: number;
    totalDb: number;
    staleCount: number;
    itemsUpdated: number;
    orphanedCount: number;
  }) => void;
  "cw:opportunities:refresh:reconciled": (data: {
    orphanedCount: number;
    removedCwIds: number[];
  }) => void;
  "cw:opportunities:refresh:skipped": (data: {
    totalCw: number;
    totalDb: number;
    staleCount: number;
    orphanedCount: number;
  }) => void;

  // Cache Events
  "cache:opportunities:refresh:started": (data: {
    totalOpportunities: number;
  }) => void;
  "cache:opportunities:refresh:completed": (data: {
    totalOpportunities: number;
    activitiesRefreshed: number;
    companiesRefreshed: number;
    notesRefreshed: number;
    contactsRefreshed: number;
    productsRefreshed: number;
    oppCwDataRefreshed: number;
    skipped: number;
  }) => void;
  "cache:opportunities:refresh:error": (data: { error: unknown }) => void;

  // Sales Metrics Cache Events
  "cache:salesMetrics:refresh:started": (data: {
    activeMemberCount: number;
    opportunityCount: number;
  }) => void;
  "cache:salesMetrics:refresh:completed": (data: {
    activeMemberCount: number;
    opportunityCount: number;
    memberMetricsWritten: number;
    cacheHitCount: number;
    cacheMissCount: number;
    durationMs: number;
  }) => void;
  "cache:salesMetrics:refresh:error": (data: {
    error: unknown;
    durationMs: number;
  }) => void;

  // ConnectWise User Defined Fields Events
  "cw:udf:refresh:started": () => void;
  "cw:udf:refresh:completed": (data: { count: number }) => void;

  // ConnectWise Members Events
  "cw:members:refresh:started": () => void;
  "cw:members:refresh:completed": (data: {
    totalMembers: number;
    totalUsers: number;
    usersUpdated: number;
  }) => void;

  // ConnectWise Members DB Sync Events
  "cw:members:db:refresh:check": () => void;
  "cw:members:db:refresh:started": (data: {
    totalCw: number;
    totalDb: number;
    staleCount: number;
  }) => void;
  "cw:members:db:refresh:completed": (data: {
    totalCw: number;
    totalDb: number;
    staleCount: number;
    itemsUpdated: number;
  }) => void;
  "cw:members:db:refresh:skipped": (data: {
    totalCw: number;
    totalDb: number;
    staleCount: number;
  }) => void;
  "worker:error": (data: { error: unknown; context?: string }) => void;
  "worker:io:connection": (data: { socket: Socket }) => void;
  "worker:io:disconnect": (data: { socket: Socket }) => void;
  "job:started": (data: { workerId: string; queueType: WorkerQueue }) => void;
  "job:log": (data: {
    message: string;
    level: JobLogLevel;
    timestamp: string;
    workerId: string;
    queueType: WorkerQueue;
  }) => void;
  "job:error": (data: {
    error: unknown;
    context?: string;
    workerId: string;
    queueType: WorkerQueue;
  }) => void;
  "job:finished": (data: { workerId: string; queueType: WorkerQueue }) => void;
}

export const events = new Eventra<EventTypes>();
