
import {
  IUser, IProject, IAsset, ITicket, IKPI, IAuditLog, IFinancialData, ICostBreakdown,
  IComplianceDoc, IHSEIncident, IRiskAssessment, IReport, ISystemSettings, ITicketActivity,
  IContract, IInventoryItem, IWorkOrder, IPMSchedule, IAlert, ICompany, IInventoryTransaction,
  TicketStatus, AssetStatus, IRole, ICustomerGroup, IContractType
} from '../types';
import { AuthService } from './authService';
import { apiClient } from './apiClient';
import { serializeTicketForUpdate } from '../utils/ticketSerialize';
import { normalizeEntityId, serializeProjectForUpdate } from '../utils/projectSerialize';

class DataService {
  private authService: AuthService;

  constructor() {
    this.authService = new AuthService();
  }

  // --- AUTH & USERS ---
  /** Danh sách đầy đủ — cần quyền manage_users (Governance, Settings). */
  async getUsers(): Promise<IUser[]> {
    const response = await apiClient.get<IUser[]>('/users');
    if (response.success && response.data) {
      return response.data;
    }
    return [];
  }

  /** Danh sách rút gọn cho gán việc — mọi user đã đăng nhập. */
  async getUserDirectory(): Promise<IUser[]> {
    try {
      const response = await apiClient.get<IUser[]>('/users/directory');
      if (response.success && response.data) {
        return response.data;
      }
    } catch {
      // Quyền hoặc mạng — không chặn trang O&M
    }
    return [];
  }

  async getCurrentUser(): Promise<IUser | null> {
    // Return user or null - let caller decide how to handle
    return await this.authService.getCurrentUser();
  }

  /** Whether identity/login is delegated to CSM. When true, user management is read-only here. */
  async isCsmManaged(): Promise<boolean> {
    try {
      const response = await apiClient.get<{ csmEnabled: boolean }>('/auth/config');
      return !!(response.success && response.data?.csmEnabled);
    } catch {
      return false;
    }
  }

  // Helper method to check authentication.
  // Auth is enforced server-side by route middleware (authenticate + permissions),
  // so here we only verify a token exists locally to fail fast with a friendly
  // message. We intentionally avoid an extra GET /auth/me round-trip: that call
  // could be slow or time out (net::ERR_CONNECTION_TIMED_OUT) and needlessly
  // break the actual mutation (e.g. creating a user) even though the request
  // itself is authenticated by the Bearer token.
  private async checkAuth(): Promise<void> {
    const token = apiClient.getToken();
    if (!token) {
      throw new Error('Not authenticated');
    }
  }

  async createUser(userData: Partial<IUser> & { password?: string }): Promise<void> {
    await this.checkAuth(); // Check auth
    const response = await apiClient.post('/users', userData);
    if (!response.success) {
      throw new Error(response.message || 'Failed to create user');
    }
  }

  async updateUser(updatedUser: IUser): Promise<IUser> {
    await this.checkAuth(); // Check auth
    const response = await apiClient.put<IUser>(`/users/${updatedUser._id}`, updatedUser);
    if (!response.success || !response.data) {
      throw new Error(response.message || 'Failed to update user');
    }
    return response.data;
  }

  async deleteUser(userId: string): Promise<void> {
    await this.checkAuth(); // Check auth
    const response = await apiClient.delete(`/users/${userId}`);
    if (!response.success) {
      throw new Error(response.message || 'Failed to delete user');
    }
  }

  async resetUserPassword(userId: string, newPass: string): Promise<void> {
    await this.checkAuth(); // Check auth
    const response = await apiClient.post(`/users/${userId}/reset-password`, { newPassword: newPass });
    if (!response.success) {
      throw new Error(response.message || 'Failed to reset password');
    }
  }

  async changePassword(userId: string, currentPass: string, newPass: string): Promise<{ success: boolean, message: string }> {
    const response = await apiClient.post(`/users/${userId}/change-password`, {
      currentPassword: currentPass,
      newPassword: newPass,
    });
    if (response.success) {
      return { success: true, message: 'Đổi mật khẩu thành công.' };
    }
    throw new Error(response.message || 'Failed to change password');
  }

  async logout(): Promise<void> {
    await this.authService.logout();
  }

  // --- ASSETS & PROJECTS ---
  async getCompanies(): Promise<ICompany[]> {
    const response = await apiClient.get<ICompany[]>('/companies');
    if (response.success && response.data) {
      return response.data;
    }
    return [];
  }

  async createCompany(company: Partial<ICompany>): Promise<void> {
    await this.checkAuth();
    const response = await apiClient.post('/companies', company);
    if (!response.success) {
      throw new Error(response.message || 'Failed to create company');
    }
  }

  async updateCompany(updatedCompany: ICompany): Promise<void> {
    await this.checkAuth();
    const response = await apiClient.put(`/companies/${updatedCompany._id}`, updatedCompany);
    if (!response.success) {
      throw new Error(response.message || 'Failed to update company');
    }
  }

  async deleteCompany(companyId: string): Promise<void> {
    await this.checkAuth();
    const response = await apiClient.delete(`/companies/${companyId}`);
    if (!response.success) {
      throw new Error(response.message || 'Failed to delete company');
    }
  }

  async getProjects(): Promise<IProject[]> {
    const response = await apiClient.get<IProject[]>('/projects');
    if (response.success && response.data) {
      return response.data;
    }
    return [];
  }

  // Legacy support
  async getSites(): Promise<IProject[]> { return this.getProjects(); }

  async createProject(project: IProject): Promise<void> {
    await this.checkAuth(); // Check auth
    const response = await apiClient.post('/projects', project);
    if (!response.success) {
      throw new Error(response.message || 'Failed to create project');
    }
  }

  async updateProject(updatedProject: IProject): Promise<void> {
    await this.checkAuth(); // Check auth
    const id = normalizeEntityId(updatedProject._id);
    if (!id) throw new Error('Invalid project id');
    const payload = serializeProjectForUpdate(updatedProject);
    const response = await apiClient.put(`/projects/${encodeURIComponent(id)}`, payload);
    if (!response.success) {
      throw new Error(response.message || 'Failed to update project');
    }
  }

  async deleteSite(projectId: string): Promise<void> {
    await this.checkAuth(); // Check auth
    const response = await apiClient.delete(`/projects/${projectId}`);
    if (!response.success) {
      throw new Error(response.message || 'Failed to delete project');
    }
  }

  async getAssets(projectId?: string): Promise<IAsset[]> {
    const endpoint = projectId ? `/assets?projectId=${projectId}` : '/assets';
    const response = await apiClient.get<IAsset[]>(endpoint);
    if (response.success && response.data) {
      return response.data;
    }
    return [];
  }

  async createAsset(asset: IAsset): Promise<void> {
    await this.checkAuth(); // Check auth
    const response = await apiClient.post('/assets', asset);
    if (!response.success) {
      throw new Error(response.message || 'Failed to create asset');
    }
  }

  async updateAsset(updatedAsset: IAsset): Promise<void> {
    await this.checkAuth(); // Check auth
    const response = await apiClient.put(`/assets/${updatedAsset._id}`, updatedAsset);
    if (!response.success) {
      throw new Error(response.message || 'Failed to update asset');
    }
  }

  async deleteAsset(assetId: string): Promise<void> {
    await this.checkAuth(); // Check auth
    const response = await apiClient.delete(`/assets/${assetId}`);
    if (!response.success) {
      throw new Error(response.message || 'Failed to delete asset');
    }
  }

  // --- TICKETS (O&M) ---
  async getTickets(projectId?: string): Promise<ITicket[]> {
    const endpoint = projectId ? `/tickets?projectId=${projectId}` : '/tickets';
    const response = await apiClient.get<ITicket[]>(endpoint);
    if (response.success && response.data) {
      return response.data;
    }
    return [];
  }

  async createTicket(ticket: ITicket): Promise<void> {
    await this.checkAuth(); // Check auth
    const response = await apiClient.post('/tickets', ticket);
    if (!response.success) {
      throw new Error(response.message || 'Failed to create ticket');
    }
  }

  async updateTicket(updatedTicket: ITicket): Promise<void> {
    await this.checkAuth(); // Check auth
    const payload = serializeTicketForUpdate(updatedTicket);
    const response = await apiClient.put(`/tickets/${updatedTicket._id}`, payload);
    if (!response.success) {
      throw new Error(response.message || 'Failed to update ticket');
    }
  }

  async deleteTicket(ticketId: string): Promise<void> {
    await this.checkAuth(); // Check auth
    const response = await apiClient.delete(`/tickets/${ticketId}`);
    if (!response.success) {
      throw new Error(response.message || 'Failed to delete ticket');
    }
  }

  async getTicketActivities(ticketId: string): Promise<ITicketActivity[]> {
    const response = await apiClient.get<ITicketActivity[]>(`/tickets/${ticketId}/activities`);
    if (response.success && response.data) {
      return response.data;
    }
    // Fallback: Generate mock activities if API not available
    const ticketResponse = await apiClient.get<ITicket>(`/tickets/${ticketId}`);
    if (ticketResponse.success && ticketResponse.data) {
      const ticket = ticketResponse.data;
      const baseActivities: ITicketActivity[] = [
        {
          _id: `act-${ticketId}-1`,
          ticketId: ticketId,
          action: 'Tạo phiếu',
          performedBy: ticket.reportedBy,
          timestamp: ticket.createdAt,
          details: 'Phiếu được tạo thành công trên hệ thống',
          statusAfter: TicketStatus.OPEN
        }
      ];
      return baseActivities;
    }
    return [];
  }

  // --- WORK ORDERS ---
  async getWorkOrders(projectId?: string): Promise<IWorkOrder[]> {
    const endpoint = projectId ? `/work-orders?projectId=${projectId}` : '/work-orders';
    const response = await apiClient.get<IWorkOrder[]>(endpoint);
    if (response.success && response.data) {
      return response.data;
    }
    return [];
  }

  async createWorkOrder(wo: IWorkOrder): Promise<void> {
    await this.checkAuth(); // Check auth
    const response = await apiClient.post('/work-orders', wo);
    if (!response.success) {
      throw new Error(response.message || 'Failed to create work order');
    }
  }

  async updateWorkOrder(wo: IWorkOrder): Promise<void> {
    await this.checkAuth(); // Check auth
    const response = await apiClient.put(`/work-orders/${wo._id}`, wo);
    if (!response.success) {
      throw new Error(response.message || 'Failed to update work order');
    }
  }

  async deleteWorkOrder(woId: string): Promise<void> {
    await this.checkAuth(); // Check auth
    const response = await apiClient.delete(`/work-orders/${woId}`);
    if (!response.success) {
      throw new Error(response.message || 'Failed to delete work order');
    }
  }

  // --- INVENTORY MANAGEMENT ---
  async getInventory(): Promise<IInventoryItem[]> {
    const response = await apiClient.get<IInventoryItem[]>('/inventory');
    if (response.success && response.data) {
      return response.data;
    }
    return [];
  }

  async createInventoryItem(item: Partial<IInventoryItem>): Promise<IInventoryItem> {
    await this.checkAuth();
    const response = await apiClient.post<IInventoryItem>('/inventory', item);
    if (!response.success || !response.data) {
      throw new Error(response.message || 'Failed to create inventory item');
    }
    return response.data;
  }

  async deleteInventoryItem(id: string): Promise<void> {
    await this.checkAuth();
    const response = await apiClient.delete(`/inventory/${id}`);
    if (!response.success) {
      throw new Error(response.message || 'Failed to delete inventory item');
    }
  }

  async getInventoryHistory(itemId?: string): Promise<IInventoryTransaction[]> {
    await this.checkAuth();
    const endpoint = itemId ? `/inventory/history?itemId=${itemId}` : '/inventory/history';
    const response = await apiClient.get<IInventoryTransaction[]>(endpoint);
    if (response.success && response.data) {
      return response.data;
    }
    return [];
  }

  // Stock in/out
  async createStockTransaction(
    itemId: string,
    type: 'In' | 'Out',
    quantity: number,
    unitCost: number = 0,
    notes: string = ''
  ): Promise<void> {
    await this.checkAuth(); // Check auth
    const endpoint = type === 'In' ? '/inventory/stock-in' : '/inventory/stock-out';
    const response = await apiClient.post(endpoint, {
      itemId,
      quantity,
      unitCost,
      notes,
    });
    if (!response.success) {
      throw new Error(response.message || `Failed to ${type === 'In' ? 'stock in' : 'stock out'}`);
    }
  }

  // --- AUTOMATION & BUSINESS LOGIC ---

  // 1. PM Scheduler Logic (Business Flow 18.3)
  async runPMScheduler(): Promise<number> {
    await this.checkAuth(); // Check auth
    const response = await apiClient.post<{ createdCount: number }>('/pm-schedules/run-scheduler');
    if (response.success && response.data) {
      return response.data.createdCount;
    }
    return 0;
  }

  // 2. Inventory Check Logic (Manual Trigger)
  async checkInventoryLevels(): Promise<void> {
    await this.checkAuth(); // Check auth
    const response = await apiClient.post('/inventory/check-levels');
    if (!response.success) {
      throw new Error(response.message || 'Failed to check inventory levels');
    }
  }

  // 3. Notification System
  async getAlerts(): Promise<IAlert[]> {
    const response = await apiClient.get<IAlert[]>('/alerts');
    if (response.success && response.data) {
      return response.data;
    }
    return [];
  }

  async createAlert(type: string, message: string, severity: 'Info' | 'Warning' | 'Critical'): Promise<void> {
    await this.checkAuth(); // Check auth
    const response = await apiClient.post('/alerts', { type, message, severity });
    if (!response.success) {
      throw new Error(response.message || 'Failed to create alert');
    }
  }

  async markAlertAsRead(alertId: string): Promise<void> {
    await this.checkAuth(); // Check auth
    const response = await apiClient.put(`/alerts/${alertId}`, { isRead: true });
    if (!response.success) {
      throw new Error(response.message || 'Failed to mark alert as read');
    }
  }

  async deleteAlert(alertId: string): Promise<void> {
    await this.checkAuth(); // Check auth
    const response = await apiClient.delete(`/alerts/${alertId}`);
    if (!response.success) {
      throw new Error(response.message || 'Failed to delete alert');
    }
  }

  // --- CONTRACTS ---
  async getContracts(projectId?: string): Promise<IContract[]> {
    const endpoint = projectId ? `/contracts?projectId=${projectId}` : '/contracts';
    const response = await apiClient.get<IContract[]>(endpoint);
    if (response.success && response.data) {
      return response.data;
    }
    return [];
  }

  async createContract(contract: Partial<IContract>): Promise<void> {
    await this.checkAuth();
    const response = await apiClient.post('/contracts', contract);
    if (!response.success) {
      throw new Error(response.message || 'Failed to create contract');
    }
  }

  async updateContract(id: string, contract: Partial<IContract>): Promise<void> {
    await this.checkAuth();
    const response = await apiClient.put(`/contracts/${id}`, contract);
    if (!response.success) {
      throw new Error(response.message || 'Failed to update contract');
    }
  }

  async deleteContract(id: string): Promise<void> {
    await this.checkAuth();
    const response = await apiClient.delete(`/contracts/${id}`);
    if (!response.success) {
      throw new Error(response.message || 'Failed to delete contract');
    }
  }

  // --- PM SCHEDULES ---
  async getPMSchedules(projectId?: string): Promise<IPMSchedule[]> {
    const endpoint = projectId ? `/pm-schedules?projectId=${projectId}` : '/pm-schedules';
    const response = await apiClient.get<IPMSchedule[]>(endpoint);
    if (response.success && response.data) {
      return response.data;
    }
    return [];
  }

  async createPMSchedule(schedule: Partial<IPMSchedule>): Promise<void> {
    await this.checkAuth();
    const response = await apiClient.post('/pm-schedules', schedule);
    if (!response.success) {
      throw new Error(response.message || 'Failed to create schedule');
    }
  }

  async updatePMSchedule(schedule: IPMSchedule): Promise<void> {
    await this.checkAuth();
    const response = await apiClient.put(`/pm-schedules/${schedule._id}`, schedule);
    if (!response.success) {
      throw new Error(response.message || 'Failed to update schedule');
    }
  }

  async deletePMSchedule(id: string): Promise<void> {
    await this.checkAuth();
    const response = await apiClient.delete(`/pm-schedules/${id}`);
    if (!response.success) {
      throw new Error(response.message || 'Failed to delete schedule');
    }
  }

  // --- KPIS & REPORTS ---
  async getKPIs(siteId: string): Promise<IKPI[]> {
    // Get directly from V2 API (live, no MongoDB)
    // This is the new default behavior
    // Use last 30 days by default
    const endDate = new Date();
    const startDate = new Date();
    startDate.setDate(startDate.getDate() - 30);
    
    return this.getKPIsLive(
      siteId,
      startDate.toISOString().split('T')[0],
      endDate.toISOString().split('T')[0]
    );
  }

  async getKPIsLive(siteId: string, startDate?: string, endDate?: string): Promise<IKPI[]> {
    // Get directly from V2 API (no MongoDB)
    let url = `/kpis/live?projectId=${siteId}`;
    if (startDate) url += `&startDate=${startDate}`;
    if (endDate) url += `&endDate=${endDate}`;
    
    try {
      const response = await apiClient.get<IKPI[]>(url);
      if (response.success && response.data) {
        return response.data;
      }
      console.warn(`[DataService] Live API returned no data:`, response);
      return [];
    } catch (error: any) {
      console.error(`[DataService] Error fetching live KPIs:`, error);
      throw error; // Re-throw to allow fallback in Dashboard
    }
  }

  async getKPIsFromMongoDB(siteId: string): Promise<IKPI[]> {
    // Legacy: Get from MongoDB (fallback option)
    const response = await apiClient.get<IKPI[]>(`/kpis?projectId=${siteId}`);
    if (response.success && response.data) {
      return response.data;
    }
    return [];
  }

  async getReports(projectId?: string): Promise<IReport[]> {
    const endpoint = projectId ? `/reports?projectId=${projectId}` : '/reports';
    const response = await apiClient.get<IReport[]>(endpoint);
    if (response.success && response.data) {
      return response.data;
    }
    return [];
  }

  async getVCOMAlarmsLive(projectId: string, status?: 'open' | 'closed', severity?: string): Promise<any[]> {
    let url = `/alerts/vcom/live?projectId=${projectId}`;
    if (status) url += `&status=${status}`;
    if (severity) url += `&severity=${severity}`;
    
    try {
      const response = await apiClient.get<any[]>(url);
      if (response.success && response.data) {
        return response.data;
      }
      console.warn(`[DataService] Live VCOM alarms API returned no data:`, response);
      return [];
    } catch (error: any) {
      console.error(`[DataService] Error fetching live VCOM alarms:`, error);
      return [];
    }
  }

  async generateReport(type: IReport['type'], title: string, projectId?: string, screenshot?: string | null, financialData?: any): Promise<IReport | null> {
    await this.checkAuth(); // Check auth
    const response = await apiClient.post<IReport>('/reports/generate', { type, title, projectId, screenshot, financialData });
    if (!response.success) {
      throw new Error(response.message || 'Failed to generate report');
    }
    return response.data ?? null;
  }

  async deleteReport(id: string): Promise<void> {
    await this.checkAuth();
    const response = await apiClient.delete(`/reports/${id}`);
    if (!response.success) {
      throw new Error(response.message || 'Failed to delete report');
    }
  }

  async downloadReport(reportId: string): Promise<Blob> {
    await this.checkAuth();
    const token = apiClient.getToken();
    const endpoint = `/reports/${reportId}/download`;
    
    // Use relative path - apiClient handles the base URL
    // Get the base URL from apiClient's internal baseURL
    const apiUrl = import.meta.env.VITE_API_URL || '/api';
    
    // Ensure relative path (not absolute)
    let url: string;
    if (apiUrl.startsWith('http://') || apiUrl.startsWith('https://')) {
      // If absolute URL, extract path
      try {
        const urlObj = new URL(apiUrl);
        url = urlObj.pathname + endpoint;
      } catch {
        url = '/api' + endpoint;
      }
    } else {
      // Relative path - browser will use current origin
      url = apiUrl + endpoint;
    }
    
    // Ensure url starts with /
    if (!url.startsWith('/')) {
      url = '/' + url;
    }
    
    const response = await fetch(url, {
      method: 'GET',
      headers: {
        'Authorization': `Bearer ${token}`,
        'Accept': 'application/pdf',
      },
      credentials: 'include', // Include cookies for CORS
    });

    if (!response.ok) {
      const errorText = await response.text().catch(() => response.statusText);
      throw new Error(`Failed to download report: ${response.status} ${errorText}`);
    }

    const blob = await response.blob();
    
    // Validate blob is actually a PDF
    if (blob.type && !blob.type.includes('pdf') && blob.size > 0) {
      // Check first bytes to see if it's actually a PDF
      const firstBytes = await blob.slice(0, 4).arrayBuffer();
      const header = String.fromCharCode(...new Uint8Array(firstBytes));
      if (header !== '%PDF') {
        console.warn('Downloaded blob does not appear to be a PDF:', {
          contentType: blob.type,
          size: blob.size,
          header: header
        });
      }
    }
    
    return blob;
  }

  // --- LOGS ---
  async getLogs(userId?: string, page: number = 1, limit: number = 100): Promise<{ data: IAuditLog[], pagination: any }> {
    const endpoint = userId
      ? `/logs?userId=${userId}&page=${page}&limit=${limit}`
      : `/logs?page=${page}&limit=${limit}`;
    const response = await apiClient.get<IAuditLog[]>(endpoint);
    if (response.success && response.data) {
      return {
        data: response.data,
        pagination: (response as any).pagination
      };
    }
    return { data: [], pagination: { hasMore: false } };
  }

  // --- FINANCIAL ---
  async getFinancialData(projectId: string): Promise<{ yearly: IFinancialData[], breakdown: ICostBreakdown[] }> {
    const response = await apiClient.get<{ yearly: IFinancialData[], breakdown: ICostBreakdown[] }>(
      `/financial/revenue?projectId=${projectId}`
    );
    if (response.success && response.data) {
      return response.data;
    }
    return { yearly: [], breakdown: [] };
  }

  // --- COMPLIANCE ---
  async getComplianceDocs(projectId: string): Promise<IComplianceDoc[]> {
    const response = await apiClient.get<IComplianceDoc[]>(`/compliance?siteId=${projectId}`);
    if (response.success && response.data) {
      return response.data;
    }
    return [];
  }

  async createComplianceDoc(doc: Partial<IComplianceDoc>): Promise<IComplianceDoc> {
    await this.checkAuth();
    const response = await apiClient.post<IComplianceDoc>('/compliance', doc);
    if (!response.success || !response.data) {
      throw new Error(response.message || 'Failed to create compliance document');
    }
    return response.data;
  }

  async updateComplianceDoc(id: string, doc: Partial<IComplianceDoc>): Promise<IComplianceDoc> {
    await this.checkAuth();
    const response = await apiClient.put<IComplianceDoc>(`/compliance/${id}`, doc);
    if (!response.success || !response.data) {
      throw new Error(response.message || 'Failed to update compliance document');
    }
    return response.data;
  }

  async deleteComplianceDoc(id: string): Promise<void> {
    await this.checkAuth();
    const response = await apiClient.delete(`/compliance/${id}`);
    if (!response.success) {
      throw new Error(response.message || 'Failed to delete compliance document');
    }
  }

  async getHSEIncidents(projectId: string): Promise<IHSEIncident[]> {
    const response = await apiClient.get<IHSEIncident[]>(`/hse-incidents?siteId=${projectId}`);
    if (response.success && response.data) {
      return response.data;
    }
    return [];
  }

  async createHSEIncident(incident: Partial<IHSEIncident>): Promise<IHSEIncident> {
    await this.checkAuth();
    const response = await apiClient.post<IHSEIncident>('/hse-incidents', incident);
    if (!response.success || !response.data) {
      throw new Error(response.message || 'Failed to create HSE incident');
    }
    return response.data;
  }

  async updateHSEIncident(id: string, incident: Partial<IHSEIncident>): Promise<IHSEIncident> {
    await this.checkAuth();
    const response = await apiClient.put<IHSEIncident>(`/hse-incidents/${id}`, incident);
    if (!response.success || !response.data) {
      throw new Error(response.message || 'Failed to update HSE incident');
    }
    return response.data;
  }

  async deleteHSEIncident(id: string): Promise<void> {
    await this.checkAuth();
    const response = await apiClient.delete(`/hse-incidents/${id}`);
    if (!response.success) {
      throw new Error(response.message || 'Failed to delete HSE incident');
    }
  }

  async getRisks(): Promise<IRiskAssessment[]> {
    const response = await apiClient.get<IRiskAssessment[]>('/risks');
    if (response.success && response.data) {
      return response.data;
    }
    return [];
  }

  // --- SETTINGS ---
  async getSystemSettings(): Promise<ISystemSettings> {
    const response = await apiClient.get<ISystemSettings>('/settings');
    if (response.success && response.data) {
      return response.data;
    }
    // Return default settings if not found
    return {
      systemName: 'VPEG AM & O&M',
      logoUrl: '',
      maintenanceMode: false,
      smtp: {
        host: '',
        port: 587,
        user: '',
        pass: '',
        secure: false,
        senderEmail: '',
      },
      retentionPolicy: {
        logDays: 365,
        reportDays: 90,
      },
    };
  }

  async updateSystemSettings(settings: ISystemSettings): Promise<void> {
    await this.checkAuth(); // Check auth
    const response = await apiClient.put('/settings', settings);
    if (!response.success) {
      throw new Error(response.message || 'Failed to update settings');
    }
  }

  async sendTestEmail(to: string): Promise<{ success: boolean, message: string }> {
    await this.checkAuth(); // Check auth
    const response = await apiClient.post('/settings/test-email', { to });
    if (response.success) {
      return { success: true, message: 'Email test đã được gửi thành công!' };
    }
    throw new Error(response.message || 'Failed to send test email');
  }

  // --- ROLES & PERMISSIONS ---
  async getRoles(): Promise<IRole[]> {
    const response = await apiClient.get<IRole[]>('/roles');
    if (response.success && response.data) {
      return response.data;
    }
    return [];
  }

  async getAllRoles(): Promise<IRole[]> {
    const response = await apiClient.get<IRole[]>('/roles/all');
    if (response.success && response.data) {
      return response.data;
    }
    return [];
  }

  async getRoleById(roleId: string): Promise<IRole | null> {
    await this.checkAuth();
    const response = await apiClient.get<IRole>(`/roles/${roleId}`);
    if (response.success && response.data) {
      return response.data;
    }
    return null;
  }

  async createRole(roleData: Partial<IRole>): Promise<IRole> {
    await this.checkAuth();
    const response = await apiClient.post<IRole>('/roles', roleData);
    if (!response.success || !response.data) {
      throw new Error(response.message || 'Failed to create role');
    }
    return response.data;
  }

  async updateRole(roleId: string, roleData: Partial<IRole>): Promise<IRole> {
    await this.checkAuth();
    const response = await apiClient.put<IRole>(`/roles/${roleId}`, roleData);
    if (!response.success || !response.data) {
      throw new Error(response.message || 'Failed to update role');
    }
    return response.data;
  }

  async updateRolePermissions(roleId: string, permissions: Record<string, boolean>): Promise<IRole> {
    await this.checkAuth();
    const response = await apiClient.put<IRole>(`/roles/${roleId}/permissions`, { permissions });
    if (!response.success || !response.data) {
      throw new Error(response.message || 'Failed to update permissions');
    }
    return response.data;
  }

  async deleteRole(roleId: string, hardDelete: boolean = false): Promise<void> {
    await this.checkAuth();
    const response = await apiClient.delete(`/roles/${roleId}${hardDelete ? '?hardDelete=true' : ''}`);
    if (!response.success) {
      throw new Error(response.message || 'Failed to delete role');
    }
  }

  async getPermissionKeys(): Promise<string[]> {
    await this.checkAuth();
    const response = await apiClient.get<string[]>('/roles/permissions/keys');
    if (response.success && response.data) {
      return response.data;
    }
    return [];
  }

  // --- CUSTOMER GROUPS ---
  async getCustomerGroups(includeInactive: boolean = false): Promise<ICustomerGroup[]> {
    const endpoint = includeInactive ? '/customer-groups?includeInactive=true' : '/customer-groups';
    const response = await apiClient.get<ICustomerGroup[]>(endpoint);
    if (response.success && response.data) {
      return response.data;
    }
    return [];
  }

  async getCustomerGroupById(groupId: string): Promise<ICustomerGroup | null> {
    await this.checkAuth();
    const response = await apiClient.get<ICustomerGroup>(`/customer-groups/${groupId}`);
    if (response.success && response.data) {
      return response.data;
    }
    return null;
  }

  async createCustomerGroup(groupData: Partial<ICustomerGroup>): Promise<ICustomerGroup> {
    await this.checkAuth();
    const response = await apiClient.post<ICustomerGroup>('/customer-groups', groupData);
    if (!response.success || !response.data) {
      throw new Error(response.message || 'Failed to create customer group');
    }
    return response.data;
  }

  async updateCustomerGroup(groupId: string, groupData: Partial<ICustomerGroup>): Promise<ICustomerGroup> {
    await this.checkAuth();
    const response = await apiClient.put<ICustomerGroup>(`/customer-groups/${groupId}`, groupData);
    if (!response.success || !response.data) {
      throw new Error(response.message || 'Failed to update customer group');
    }
    return response.data;
  }

  async deleteCustomerGroup(groupId: string, hardDelete: boolean = false): Promise<void> {
    await this.checkAuth();
    const response = await apiClient.delete(`/customer-groups/${groupId}${hardDelete ? '?hardDelete=true' : ''}`);
    if (!response.success) {
      throw new Error(response.message || 'Failed to delete customer group');
    }
  }

  // --- CONTRACT TYPES ---
  async getContractTypes(includeInactive: boolean = false): Promise<IContractType[]> {
    const endpoint = includeInactive ? '/contract-types?includeInactive=true' : '/contract-types';
    const response = await apiClient.get<IContractType[]>(endpoint);
    if (response.success && response.data) {
      return response.data;
    }
    return [];
  }

  async getContractTypeById(typeId: string): Promise<IContractType | null> {
    await this.checkAuth();
    const response = await apiClient.get<IContractType>(`/contract-types/${typeId}`);
    if (response.success && response.data) {
      return response.data;
    }
    return null;
  }

  async createContractType(typeData: Partial<IContractType>): Promise<IContractType> {
    await this.checkAuth();
    const response = await apiClient.post<IContractType>('/contract-types', typeData);
    if (!response.success || !response.data) {
      throw new Error(response.message || 'Failed to create contract type');
    }
    return response.data;
  }

  async updateContractType(typeId: string, typeData: Partial<IContractType>): Promise<IContractType> {
    await this.checkAuth();
    const response = await apiClient.put<IContractType>(`/contract-types/${typeId}`, typeData);
    if (!response.success || !response.data) {
      throw new Error(response.message || 'Failed to update contract type');
    }
    return response.data;
  }

  async deleteContractType(typeId: string, hardDelete: boolean = false): Promise<void> {
    await this.checkAuth();
    const response = await apiClient.delete(`/contract-types/${typeId}${hardDelete ? '?hardDelete=true' : ''}`);
    if (!response.success) {
      throw new Error(response.message || 'Failed to delete contract type');
    }
  }
}

export const dataService = new DataService();
