import axios, { AxiosInstance } from 'axios';
import type { eResidentCredential, eCitizenCredential } from '@the-order/schemas';

export interface IssueVCRequest {
  subject: string;
  credentialSubject: Record<string, unknown>;
  expirationDate?: string;
}

export interface VerifyVCRequest {
  credential: {
    id: string;
    proof?: {
      jws: string;
      verificationMethod: string;
    };
  };
}

export interface BatchIssuanceRequest {
  credentials: Array<{
    subject: string;
    credentialSubject: Record<string, unknown>;
    expirationDate?: string;
  }>;
}

export interface CredentialMetrics {
  issuedToday: number;
  issuedThisWeek: number;
  issuedThisMonth: number;
  issuedThisYear: number;
  successRate: number;
  failureRate: number;
  totalIssuances: number;
  totalFailures: number;
  averageIssuanceTime: number;
  p50IssuanceTime: number;
  p95IssuanceTime: number;
  p99IssuanceTime: number;
  byCredentialType: Record<string, number>;
  byAction: Record<string, number>;
  recentIssuances: Array<{
    credentialId: string;
    credentialType: string[];
    issuedAt: Date;
    subjectDid: string;
  }>;
}

export class IdentityClient {
  protected client: AxiosInstance;

  constructor(baseURL?: string) {
    const apiBaseURL =
      baseURL ||
      (typeof window !== 'undefined'
        ? process.env.NEXT_PUBLIC_IDENTITY_SERVICE_URL || 'http://localhost:4002'
        : 'http://localhost:4002');

    this.client = axios.create({
      baseURL: apiBaseURL,
      headers: {
        'Content-Type': 'application/json',
      },
    });

    // Set up request interceptor for authentication
    this.client.interceptors.request.use(
      (config) => {
        const token = this.getAuthToken();
        if (token) {
          config.headers.Authorization = `Bearer ${token}`;
        }
        return config;
      },
      (error) => Promise.reject(error)
    );
  }

  private getAuthToken(): string | null {
    if (typeof window === 'undefined') return null;
    return localStorage.getItem('auth_token');
  }

  setAuthToken(token: string): void {
    if (typeof window !== 'undefined') {
      localStorage.setItem('auth_token', token);
    }
  }

  clearAuthToken(): void {
    if (typeof window !== 'undefined') {
      localStorage.removeItem('auth_token');
    }
  }

  async issueCredential(request: IssueVCRequest): Promise<{ credential: eResidentCredential | eCitizenCredential }> {
    const response = await this.client.post<{ credential: eResidentCredential | eCitizenCredential }>('/vc/issue', request);
    return response.data;
  }

  async verifyCredential(request: VerifyVCRequest): Promise<{ valid: boolean }> {
    const response = await this.client.post<{ valid: boolean }>('/vc/verify', request);
    return response.data;
  }

  async batchIssue(request: BatchIssuanceRequest): Promise<{
    jobId: string;
    total: number;
    accepted: number;
    results: Array<{
      index: number;
      credentialId?: string;
      error?: string;
    }>;
  }> {
    const response = await this.client.post<{
      jobId: string;
      total: number;
      accepted: number;
      results: Array<{
        index: number;
        credentialId?: string;
        error?: string;
      }>;
    }>('/vc/issue/batch', request);
    return response.data;
  }

  async revokeCredential(credentialId: string, reason?: string): Promise<void> {
    await this.client.post('/vc/revoke', { credentialId, reason });
  }

  async getMetrics(startDate?: Date, endDate?: Date): Promise<CredentialMetrics> {
    const params = new URLSearchParams();
    if (startDate) params.append('startDate', startDate.toISOString());
    if (endDate) params.append('endDate', endDate.toISOString());
    const response = await this.client.get<CredentialMetrics>(`/metrics?${params.toString()}`);
    return response.data;
  }

  async getMetricsDashboard(): Promise<{
    summary: CredentialMetrics;
    trends: {
      daily: Array<{ date: string; count: number }>;
      weekly: Array<{ week: string; count: number }>;
      monthly: Array<{ month: string; count: number }>;
    };
    topCredentialTypes: Array<{ type: string; count: number; percentage: number }>;
  }> {
    const response = await this.client.get<{
      summary: CredentialMetrics;
      trends: {
        daily: Array<{ date: string; count: number }>;
        weekly: Array<{ week: string; count: number }>;
        monthly: Array<{ month: string; count: number }>;
      };
      topCredentialTypes: Array<{ type: string; count: number; percentage: number }>;
    }>('/metrics/dashboard');
    return response.data;
  }

  async searchAuditLogs(filters: {
    credentialId?: string;
    issuerDid?: string;
    subjectDid?: string;
    credentialType?: string | string[];
    action?: 'issued' | 'revoked' | 'verified' | 'renewed';
    performedBy?: string;
    startDate?: string;
    endDate?: string;
    ipAddress?: string;
    page?: number;
    pageSize?: number;
  }): Promise<{
    logs: Array<{
      id: string;
      action: string;
      credentialId?: string;
      subjectDid?: string;
      performedBy?: string;
      timestamp: string;
      metadata?: Record<string, unknown>;
    }>;
    total: number;
    page: number;
    pageSize: number;
  }> {
    const response = await this.client.post<{
      logs: Array<{
        id: string;
        action: string;
        credentialId?: string;
        subjectDid?: string;
        performedBy?: string;
        timestamp: string;
        metadata?: Record<string, unknown>;
      }>;
      total: number;
      page: number;
      pageSize: number;
    }>('/metrics/audit/search', filters);
    return response.data;
  }
}

