import 'tenant.dart';

enum PlatformRole {
  superAdmin,
  support,
  financeOps,
  operations,
  readOnly,
  ;

  String get value => switch (this) {
        PlatformRole.superAdmin => 'super_admin',
        PlatformRole.support => 'support',
        PlatformRole.financeOps => 'finance_ops',
        PlatformRole.operations => 'operations',
        PlatformRole.readOnly => 'read_only',
      };

  String get label => switch (this) {
        PlatformRole.superAdmin => 'Super Admin',
        PlatformRole.support => 'Destek',
        PlatformRole.financeOps => 'Finans Operasyon',
        PlatformRole.operations => 'Operasyon',
        PlatformRole.readOnly => 'Sadece Görüntüleme',
      };

  static PlatformRole parse(String raw) => switch (raw) {
        'super_admin' => PlatformRole.superAdmin,
        'support' => PlatformRole.support,
        'finance_ops' => PlatformRole.financeOps,
        'operations' => PlatformRole.operations,
        'read_only' => PlatformRole.readOnly,
        _ => PlatformRole.readOnly,
      };
}

class PlatformMembership {
  const PlatformMembership({
    required this.id,
    required this.userId,
    required this.role,
    this.status = 'active',
  });

  final String id;
  final String userId;
  final PlatformRole role;
  final String status;

  bool get isActive => status == 'active';
  bool get isSuperAdmin => role == PlatformRole.superAdmin && isActive;
  bool get canManageBilling =>
      isActive &&
      (role == PlatformRole.superAdmin || role == PlatformRole.financeOps);
  bool get canManageTenants =>
      isActive &&
      (role == PlatformRole.superAdmin ||
          role == PlatformRole.operations ||
          role == PlatformRole.support);

  factory PlatformMembership.fromJson(Map<String, dynamic> json) {
    return PlatformMembership(
      id: json['id'] as String,
      userId: json['user_id'] as String,
      role: PlatformRole.parse(json['role'] as String? ?? ''),
      status: (json['status'] as String?) ?? 'active',
    );
  }
}

enum SubscriptionStatus { trialing, active, pastDue, cancelled, paused }

extension SubscriptionStatusX on SubscriptionStatus {
  String get value => switch (this) {
        SubscriptionStatus.trialing => 'trialing',
        SubscriptionStatus.active => 'active',
        SubscriptionStatus.pastDue => 'past_due',
        SubscriptionStatus.cancelled => 'cancelled',
        SubscriptionStatus.paused => 'paused',
      };

  static SubscriptionStatus parse(String raw) => switch (raw) {
        'trialing' => SubscriptionStatus.trialing,
        'active' => SubscriptionStatus.active,
        'past_due' => SubscriptionStatus.pastDue,
        'cancelled' => SubscriptionStatus.cancelled,
        'paused' => SubscriptionStatus.paused,
        _ => SubscriptionStatus.trialing,
      };
}

class TenantSubscription {
  const TenantSubscription({
    required this.id,
    required this.tenantId,
    required this.plan,
    required this.status,
    this.billingProvider,
    this.providerCustomerId,
    this.providerSubscriptionId,
    this.periodStart,
    this.periodEnd,
    this.aiMonthlyCredits = 0,
    this.aiBonusCredits = 0,
  });

  final String id;
  final String tenantId;
  final TenantPlan plan;
  final SubscriptionStatus status;
  final String? billingProvider;
  final String? providerCustomerId;
  final String? providerSubscriptionId;
  final DateTime? periodStart;
  final DateTime? periodEnd;
  final int aiMonthlyCredits;
  final int aiBonusCredits;

  int get totalAiCredits => aiMonthlyCredits + aiBonusCredits;

  factory TenantSubscription.fromJson(Map<String, dynamic> json) {
    return TenantSubscription(
      id: json['id'] as String,
      tenantId: json['tenant_id'] as String,
      plan: Tenant.parsePlanValue(json['plan'] as String?),
      status: SubscriptionStatusX.parse(json['status'] as String? ?? ''),
      billingProvider: json['billing_provider'] as String?,
      providerCustomerId: json['provider_customer_id'] as String?,
      providerSubscriptionId: json['provider_subscription_id'] as String?,
      periodStart: _parseDate(json['period_start']),
      periodEnd: _parseDate(json['period_end']),
      aiMonthlyCredits: (json['ai_monthly_credits'] as num?)?.toInt() ?? 0,
      aiBonusCredits: (json['ai_bonus_credits'] as num?)?.toInt() ?? 0,
    );
  }
}

enum AiCreditEntryType {
  monthlyAllocation,
  bonusAllocation,
  usageDebit,
  manualAdjustment,
  refund,
  expire,
  ;

  String get value => switch (this) {
        AiCreditEntryType.monthlyAllocation => 'monthly_allocation',
        AiCreditEntryType.bonusAllocation => 'bonus_allocation',
        AiCreditEntryType.usageDebit => 'usage_debit',
        AiCreditEntryType.manualAdjustment => 'manual_adjustment',
        AiCreditEntryType.refund => 'refund',
        AiCreditEntryType.expire => 'expire',
      };

  static AiCreditEntryType parse(String raw) => switch (raw) {
        'monthly_allocation' => AiCreditEntryType.monthlyAllocation,
        'bonus_allocation' => AiCreditEntryType.bonusAllocation,
        'usage_debit' => AiCreditEntryType.usageDebit,
        'manual_adjustment' => AiCreditEntryType.manualAdjustment,
        'refund' => AiCreditEntryType.refund,
        'expire' => AiCreditEntryType.expire,
        _ => AiCreditEntryType.manualAdjustment,
      };
}

class AiCreditLedgerEntry {
  const AiCreditLedgerEntry({
    required this.id,
    required this.tenantId,
    required this.entryType,
    required this.delta,
    required this.balanceAfter,
    this.referenceType,
    this.referenceId,
    this.note,
    this.createdByUserId,
    this.createdAt,
  });

  final String id;
  final String tenantId;
  final AiCreditEntryType entryType;
  final int delta;
  final int balanceAfter;
  final String? referenceType;
  final String? referenceId;
  final String? note;
  final String? createdByUserId;
  final DateTime? createdAt;

  factory AiCreditLedgerEntry.fromJson(Map<String, dynamic> json) {
    return AiCreditLedgerEntry(
      id: json['id'] as String,
      tenantId: json['tenant_id'] as String,
      entryType: AiCreditEntryType.parse(json['entry_type'] as String? ?? ''),
      delta: (json['delta'] as num?)?.toInt() ?? 0,
      balanceAfter: (json['balance_after'] as num?)?.toInt() ?? 0,
      referenceType: json['reference_type'] as String?,
      referenceId: json['reference_id'] as String?,
      note: json['note'] as String?,
      createdByUserId: json['created_by_user_id'] as String?,
      createdAt: _parseDate(json['created']),
    );
  }
}

class AiUsageLog {
  const AiUsageLog({
    required this.id,
    required this.tenantId,
    required this.userId,
    required this.action,
    required this.creditCost,
    this.model,
    this.jobId,
    this.tokenInput,
    this.tokenOutput,
    this.latencyMs,
    this.createdAt,
  });

  final String id;
  final String tenantId;
  final String userId;
  final String action;
  final int creditCost;
  final String? model;
  final String? jobId;
  final int? tokenInput;
  final int? tokenOutput;
  final int? latencyMs;
  final DateTime? createdAt;

  factory AiUsageLog.fromJson(Map<String, dynamic> json) {
    return AiUsageLog(
      id: json['id'] as String,
      tenantId: json['tenant_id'] as String,
      userId: json['user_id'] as String,
      action: json['action'] as String? ?? '',
      creditCost: (json['credit_cost'] as num?)?.toInt() ?? 0,
      model: json['model'] as String?,
      jobId: json['job_id'] as String?,
      tokenInput: (json['token_input'] as num?)?.toInt(),
      tokenOutput: (json['token_output'] as num?)?.toInt(),
      latencyMs: (json['latency_ms'] as num?)?.toInt(),
      createdAt: _parseDate(json['created']),
    );
  }
}

class AdminAuditLog {
  const AdminAuditLog({
    required this.id,
    required this.actorUserId,
    required this.actorRole,
    required this.actionType,
    this.targetCollection,
    this.targetRecordId,
    this.targetTenantId,
    this.summary,
    this.metadata,
    this.createdAt,
  });

  final String id;
  final String actorUserId;
  final PlatformRole actorRole;
  final String actionType;
  final String? targetCollection;
  final String? targetRecordId;
  final String? targetTenantId;
  final String? summary;
  final Map<String, dynamic>? metadata;
  final DateTime? createdAt;

  factory AdminAuditLog.fromJson(Map<String, dynamic> json) {
    final metadata = json['metadata'];
    return AdminAuditLog(
      id: json['id'] as String,
      actorUserId: json['actor_user_id'] as String,
      actorRole: PlatformRole.parse(json['actor_role'] as String? ?? ''),
      actionType: json['action_type'] as String? ?? '',
      targetCollection: json['target_collection'] as String?,
      targetRecordId: json['target_record_id'] as String?,
      targetTenantId: json['target_tenant_id'] as String?,
      summary: json['summary'] as String?,
      metadata: metadata is Map<String, dynamic> ? metadata : null,
      createdAt: _parseDate(json['created']),
    );
  }
}

DateTime? _parseDate(dynamic raw) {
  final value = raw as String?;
  if (value == null || value.isEmpty) return null;
  return DateTime.tryParse(value);
}
