/* eslint-disable @typescript-eslint/no-explicit-any */
"use client";

export enum LogType {
  API = "API",
  SOCKET = "SOCKET",
  ERROR = "ERROR",
  INFO = "INFO",
}

export enum LogDirection {
  REQUEST = "REQUEST",
  RESPONSE = "RESPONSE",
  INCOMING = "INCOMING",
  OUTGOING = "OUTGOING",
}

interface LogEntry {
  type: LogType;
  direction?: LogDirection;
  event: string;
  data?: unknown;
  url?: string;
  method?: string;
  status?: number;
  timestamp: Date;
  duration?: number;
}

class DevLogger {
  private enabled = false;
  private enabledTypes = new Set<LogType>(Object.values(LogType));
  private envEnabled = false;
  private serverLoggingEnabled = false;

  constructor() {
    // Check ENV variables first
    if (typeof window !== "undefined") {
      this.envEnabled = process.env.NEXT_PUBLIC_DEV_LOGGER_ENABLED !== "false";
    } else {
      // Server side - check server env
      this.serverLoggingEnabled =
        process.env.DEV_LOGGER_SERVER_ENABLED === "true";
      this.envEnabled = process.env.DEV_LOGGER_ENABLED !== "false";
    }

    // Check localStorage for logging preferences (client-side only)
    if (typeof window !== "undefined") {
      const stored = localStorage.getItem("dev-logger-enabled");
      this.enabled = stored ? JSON.parse(stored) : this.envEnabled;

      const storedTypes = localStorage.getItem("dev-logger-types");
      if (storedTypes) {
        this.enabledTypes = new Set(JSON.parse(storedTypes));
      }
    } else {
      this.enabled = this.envEnabled;
    }
  }

  private shouldLog(type: LogType): boolean {
    // Check ENV first, then user preferences
    return this.envEnabled && this.enabled && this.enabledTypes.has(type);
  }

  private shouldLogServer(type: LogType): boolean {
    // Server logging requires explicit ENV enable
    return (
      this.serverLoggingEnabled &&
      this.envEnabled &&
      this.enabled &&
      this.enabledTypes.has(type)
    );
  }

  private getLogStyle(
    type: LogType,
    direction?: LogDirection
  ): { emoji: string; color: string; bgColor?: string } {
    const styles: Record<LogType, any> = {
      [LogType.API]: {
        [LogDirection.REQUEST]: {
          emoji: "🚀",
          color: "#3b82f6",
          bgColor: "#eff6ff",
        },
        [LogDirection.RESPONSE]: {
          emoji: "📨",
          color: "#10b981",
          bgColor: "#f0fdf4",
        },
      },
      [LogType.SOCKET]: {
        [LogDirection.OUTGOING]: { emoji: "🟢", color: "#16a34a" },
        [LogDirection.INCOMING]: { emoji: "🔵", color: "#2563eb" },
      },
      [LogType.ERROR]: { emoji: "❌", color: "#ef4444" },
      [LogType.INFO]: { emoji: "ℹ️", color: "#6366f1" },
    };

    const typeStyles = styles[type];
    if (
      direction &&
      typeof typeStyles === "object" &&
      direction in typeStyles
    ) {
      return typeStyles[direction];
    }
    return typeof typeStyles === "object"
      ? { emoji: "📝", color: "#6b7280" }
      : typeStyles;
  }

  private formatTime(date: Date): string {
    return date.toLocaleTimeString("en-US", {
      hour12: false,
      hour: "2-digit",
      minute: "2-digit",
      second: "2-digit",
      fractionalSecondDigits: 3,
    });
  }

  log(entry: Omit<LogEntry, "timestamp">) {
    if (!this.shouldLog(entry.type)) return;

    const timestamp = new Date();
    const { emoji, color, bgColor } = this.getLogStyle(
      entry.type,
      entry.direction
    );
    const timeStr = this.formatTime(timestamp);
    const baseStyle = `color: ${color}; font-weight: bold;`;
    const groupStyle = bgColor
      ? `${baseStyle} background: ${bgColor}; padding: 2px 6px; border-radius: 3px;`
      : baseStyle;

    // Create compact collapsible group
    const groupTitle = `${emoji} ${entry.type}${
      entry.direction ? ` ${entry.direction}` : ""
    }: ${entry.event}`;

    // Always use groupCollapsed for cleaner output
    console.groupCollapsed(`%c${groupTitle} [${timeStr}]`, groupStyle);

    // Compact one-line summary with key info
    const summaryParts = [];
    if (entry.method) summaryParts.push(`${entry.method}`);
    if (entry.status) {
      const statusColor =
        entry.status >= 200 && entry.status < 300 ? "✅" : "❌";
      summaryParts.push(`${statusColor} ${entry.status}`);
    }
    if (entry.duration !== undefined)
      summaryParts.push(`⏱️ ${entry.duration}ms`);

    if (summaryParts.length > 0) {
      console.log(
        `%c${summaryParts.join(" • ")}`,
        "color: #6b7280; font-size: 11px;"
      );
    }

    if (entry.data !== undefined) {
      // Show preview for objects/arrays, full value for primitives
      if (typeof entry.data === "object" && entry.data !== null) {
        const preview = Array.isArray(entry.data)
          ? `Array[${entry.data.length}]`
          : `Object{${Object.keys(entry.data).slice(0, 3).join(", ")}${
              Object.keys(entry.data).length > 3 ? "..." : ""
            }}`;
        console.log(`%c📦 Data:`, "color: #6b7280; font-size: 11px;", preview);
        console.log(entry.data);
      } else {
        console.log(
          `%c📦 Data:`,
          "color: #6b7280; font-size: 11px;",
          entry.data
        );
      }
    }

    console.groupEnd();
  }

  // API logging methods
  apiRequest(url: string, method: string, data?: unknown) {
    this.log({
      type: LogType.API,
      direction: LogDirection.REQUEST,
      event: `${method.toUpperCase()} ${url.split("?")[0]}`,
      url,
      method,
      data,
    });
  }

  apiResponse(
    url: string,
    method: string,
    status: number,
    data?: unknown,
    duration?: number
  ) {
    this.log({
      type: LogType.API,
      direction: LogDirection.RESPONSE,
      event: `${method.toUpperCase()} ${url.split("?")[0]}`,
      url,
      method,
      status,
      data,
      duration,
    });
  }

  // Socket logging methods
  socketOutgoing(event: string, data?: unknown) {
    this.log({
      type: LogType.SOCKET,
      direction: LogDirection.OUTGOING,
      event,
      data,
    });
  }

  socketIncoming(event: string, data?: unknown) {
    this.log({
      type: LogType.SOCKET,
      direction: LogDirection.INCOMING,
      event,
      data,
    });
  }

  // Connection state logging
  socketConnected() {
    console.log(
      `%c✅ SOCKET CONNECTED`,
      "color: #10b981; font-weight: bold; background: #f0fdf4; padding: 2px 6px; border-radius: 3px;"
    );
  }

  socketDisconnected(reason?: string) {
    console.log(
      `%c❌ SOCKET DISCONNECTED`,
      "color: #ef4444; font-weight: bold; background: #fef2f2; padding: 2px 6px; border-radius: 3px;",
      reason || ""
    );
  }

  socketError(error?: unknown) {
    console.log(
      `%c⚠️ SOCKET ERROR`,
      "color: #f59e0b; font-weight: bold; background: #fffbeb; padding: 2px 6px; border-radius: 3px;",
      error || ""
    );
  }

  // Server-side logging methods
  serverApiRequest(url: string, method: string, body?: unknown) {
    if (!this.shouldLogServer(LogType.API)) return;

    console.group(`\n🚀 [SERVER] API REQUEST: ${method} ${url}`);
    if (body !== undefined) {
      console.log("📦 Request Body:", JSON.stringify(body, null, 2));
    }
    console.groupEnd();
  }

  serverApiResponse(
    url: string,
    method: string,
    status: number,
    data?: unknown,
    duration?: number
  ) {
    if (!this.shouldLogServer(LogType.API)) return;

    const emoji = status >= 200 && status < 300 ? "✅" : "❌";
    console.group(
      `\n${emoji} [SERVER] API ${
        status >= 200 && status < 300 ? "SUCCESS" : "ERROR"
      }: ${method} ${url}`
    );
    console.log(`📊 Status: ${status}`);
    if (duration !== undefined) {
      console.log(`⏱️ Duration: ${duration}ms`);
    }
    if (data !== undefined) {
      // Limit response data display to avoid overwhelming logs
      const responsePreview =
        typeof data === "object" && data !== null
          ? Array.isArray(data)
            ? `Array[${data.length}]`
            : `Object{${Object.keys(data).slice(0, 5).join(", ")}${
                Object.keys(data).length > 5 ? "..." : ""
              }}`
          : data;
      console.log("📦 Response Preview:", responsePreview);
      // Full response data (collapsed)
      console.groupCollapsed("📄 Full Response Data:");
      console.log(data);
      console.groupEnd();
    }
    console.groupEnd();
  }

  // Control methods
  enable() {
    this.enabled = true;
    if (typeof window !== "undefined") {
      localStorage.setItem("dev-logger-enabled", "true");
    }
    console.log(
      "%c📝 Dev Logger ENABLED",
      "color: #10b981; font-weight: bold;"
    );
  }

  disable() {
    this.enabled = false;
    if (typeof window !== "undefined") {
      localStorage.setItem("dev-logger-enabled", "false");
    }
    console.log(
      "%c📝 Dev Logger DISABLED",
      "color: #ef4444; font-weight: bold;"
    );
  }

  enableType(type: LogType) {
    this.enabledTypes.add(type);
    this.saveEnabledTypes();
    console.log(
      `%c📝 ${type} logging ENABLED`,
      "color: #10b981; font-weight: bold;"
    );
  }

  disableType(type: LogType) {
    this.enabledTypes.delete(type);
    this.saveEnabledTypes();
    console.log(
      `%c📝 ${type} logging DISABLED`,
      "color: #ef4444; font-weight: bold;"
    );
  }

  private saveEnabledTypes() {
    if (typeof window !== "undefined") {
      localStorage.setItem(
        "dev-logger-types",
        JSON.stringify(Array.from(this.enabledTypes))
      );
    }
  }

  // Helper method to show current settings
  status() {
    console.group(
      "%c🔧 Dev Logger Status",
      "color: #6366f1; font-weight: bold;"
    );
    console.log("Enabled:", this.enabled);
    console.log("Active Types:", Array.from(this.enabledTypes));
    console.groupEnd();
  }
}

// Create singleton instance
export const devLogger = new DevLogger();

// Make it available globally for easy console access
if (typeof window !== "undefined") {
  (window as any).devLogger = devLogger;
}

// Export convenience methods for quick filtering
export const filterAPI = () => {
  console.clear();
  devLogger.disableType(LogType.SOCKET);
  devLogger.disableType(LogType.ERROR);
  devLogger.disableType(LogType.INFO);
  devLogger.enableType(LogType.API);
};

export const filterSocket = () => {
  console.clear();
  devLogger.disableType(LogType.API);
  devLogger.disableType(LogType.ERROR);
  devLogger.disableType(LogType.INFO);
  devLogger.enableType(LogType.SOCKET);
};

export const showAll = () => {
  console.clear();
  Object.values(LogType).forEach((type) => devLogger.enableType(type));
};
