// src/client/entities/appConfig.ts
// App configuration entity - Pinia store for managing enabled modules

import { defineStore } from 'pinia';
import { z } from 'zod';
import { api, type RequestConfig } from '../shared/api/api.client';
import { USER_ROLES, type UserRole } from '@shared/constants/roles';
import type { RoleColorValue } from '@shared/contracts/system';

// Zod schema for system module response
const SystemModuleSchema = z.object({
  id: z.string(),
  moduleId: z.string(),
  isEnabled: z.boolean(),
  createdAt: z.string().or(z.date()),
  updatedAt: z.string().or(z.date()),
});

// Schema for array of modules (interceptor already unwraps .data)
const ModulesResponseSchema = z.array(SystemModuleSchema);

const RoleColorsResponseSchema = z.array(z.object({
  id: z.string(),
  role: z.string(),
  privateNormal: z.string(),
  privateHigh: z.string(),
  publicNormal: z.string(),
  publicHigh: z.string(),
  createdAt: z.string().or(z.date()),
  updatedAt: z.string().or(z.date()),
}));

export const DEFAULT_ROLE_NOTE_COLORS: RoleColorValue = {
  privateNormal: '#94a3b8',
  privateHigh: '#475569',
  publicNormal: '#3b82f6',
  publicHigh: '#1d4ed8',
};

const DEFAULT_ROLE_COLORS: Record<string, RoleColorValue> = {
  [USER_ROLES.GOD]: { privateNormal: '#f43f5e', privateHigh: '#be123c', publicNormal: '#ef4444', publicHigh: '#991b1b' },
  [USER_ROLES.ADMIN]: { privateNormal: '#f59e0b', privateHigh: '#b45309', publicNormal: '#d97706', publicHigh: '#92400e' },
  [USER_ROLES.MANAGER]: { privateNormal: '#3b82f6', privateHigh: '#1d4ed8', publicNormal: '#0ea5e9', publicHigh: '#0369a1' },
  [USER_ROLES.MAID]: { privateNormal: '#22c55e', privateHigh: '#15803d', publicNormal: '#16a34a', publicHigh: '#166534' },
};

// Cache duration in milliseconds (5 minutes)
const CACHE_DURATION = 5 * 60 * 1000;

/**
 * App configuration store
 * Manages the list of enabled modules from backend
 */
export const useAppConfigStore = defineStore('appConfig', {
  state: () => ({
    enabledModules: [] as string[],
    roleColors: { ...DEFAULT_ROLE_COLORS } as Record<string, RoleColorValue>,
    isLoading: false as boolean,
    isLoadingRoleColors: false as boolean,
    error: null as string | null,
    roleColorsError: null as string | null,
    lastFetchTime: null as number | null,
  }),

  getters: {
    /**
     * Check if a module is enabled
     */
    isModuleEnabled: (state) => (moduleName: string): boolean => {
      return state.enabledModules.includes(moduleName);
    },

    /**
     * Check if config has been loaded and is still fresh
     * Returns false if more than 5 minutes have passed since last fetch
     * or if this is the first session (no modules loaded)
     */
    isLoaded: (state) => {
      // If no modules loaded, consider it not loaded
      if (state.enabledModules.length === 0) {
        return false;
      }
      // If no fetch time recorded, consider it not loaded
      if (state.lastFetchTime === null) {
        return false;
      }
      // Check if cache is stale (more than 5 minutes)
      const isStale = Date.now() - state.lastFetchTime > CACHE_DURATION;
      return !isStale;
    },
  },

  actions: {
    /**
     * Fetch enabled modules from backend
     */
    async fetchConfig(): Promise<void> {
      try {
        this.isLoading = true;
        this.error = null;

        // Ожидаем сразу массив (без обертки success/data)
        const modules = await api.get<Array<{ moduleId: string; isEnabled: boolean }>>('/system/modules', {
          schema: ModulesResponseSchema,
        } as RequestConfig<Array<{ moduleId: string; isEnabled: boolean }>>);

        // Extract module IDs from enabled modules
        this.enabledModules = modules
          .filter((module) => module.isEnabled)
          .map((module) => module.moduleId);

        try {
          await this.fetchRoleColors();
        } catch (roleColorsError) {
          console.warn('[AppConfig] Failed to fetch role colors, fallback palette will be used:', roleColorsError);
        }

        this.lastFetchTime = Date.now();
      } catch (error: any) {
        this.error = error.message || 'Failed to fetch config';
        console.error('[AppConfig] Failed to fetch config:', error);
        throw error;
      } finally {
        this.isLoading = false;
      }
    },

    /**
     * Refresh config from backend
     */
    async refreshConfig(): Promise<void> {
      await this.fetchConfig();
    },

    async fetchRoleColors(): Promise<void> {
      try {
        this.isLoadingRoleColors = true;
        this.roleColorsError = null;

        const roleColors = await api.get<Array<{ role: string; privateNormal: string; privateHigh: string; publicNormal: string; publicHigh: string }>>('/system/role-colors', {
          schema: RoleColorsResponseSchema,
        } as RequestConfig<Array<{ role: string; privateNormal: string; privateHigh: string; publicNormal: string; publicHigh: string }>>);

        const normalized: Record<string, RoleColorValue> = { ...DEFAULT_ROLE_COLORS };
        roleColors.forEach((item) => {
          normalized[item.role] = {
            privateNormal: item.privateNormal,
            privateHigh: item.privateHigh,
            publicNormal: item.publicNormal,
            publicHigh: item.publicHigh,
          };
        });

        this.roleColors = normalized;
      } catch (error: any) {
        this.roleColorsError = error.message || 'Failed to fetch role colors';
        this.roleColors = { ...DEFAULT_ROLE_COLORS };
        throw error;
      } finally {
        this.isLoadingRoleColors = false;
      }
    },

    async updateRoleColors(role: string, colors: RoleColorValue): Promise<void> {
      await api.put(`/system/role-colors/${role}`, colors);
      this.roleColors = {
        ...this.roleColors,
        [role]: { ...colors },
      };
    },

    getRoleColors(role: string | null | undefined): RoleColorValue {
      if (!role) return DEFAULT_ROLE_NOTE_COLORS;
      return this.roleColors[role] || DEFAULT_ROLE_COLORS[role] || DEFAULT_ROLE_NOTE_COLORS;
    },

    /**
     * Clear config state
     */
    clearConfig(): void {
      this.enabledModules = [];
      this.roleColors = { ...DEFAULT_ROLE_COLORS };
      this.error = null;
      this.roleColorsError = null;
      this.lastFetchTime = null;
    },
  },

  // Configure persist to exclude lastFetchTime from localStorage
  // This ensures that on page refresh, the config is treated as stale
  persist: {
    key: 'appConfig',
    storage: localStorage,
    pick: ['enabledModules', 'roleColors', 'lastFetchTime'], // Persist modules + role palettes
  },
});
