import 'job.dart';

enum TenantKind { lab, clinic }

enum TenantRole {
  owner,
  admin,
  technician, // lab: işler + ürünler
  delivery, // lab: işler
  finance, // lab+clinic: finans
  doctor, // clinic: işler + hastalar
  member, // legacy — full access
  ;

  String get value => name;

  String get label => switch (this) {
        TenantRole.owner => 'Sahibi',
        TenantRole.admin => 'Yönetici',
        TenantRole.technician => 'Teknisyen',
        TenantRole.delivery => 'Teslimat Elemanı',
        TenantRole.finance => 'Finans Elemanı',
        TenantRole.doctor => 'Hekim',
        TenantRole.member => 'Üye',
      };
}

enum TenantPlan { starter, pro, enterprise }

class Tenant {
  const Tenant({
    required this.id,
    required this.kind,
    required this.memberNumber,
    required this.companyName,
    this.companyAddress,
    this.city,
    this.district,
    this.latitude,
    this.longitude,
    this.logo,
    this.defaultCurrency = 'TRY',
    this.status = 'active',
    this.plan,
    this.maxMembers,
    this.workflowOverrideStepKeys = const [],
  });

  final String id;
  final TenantKind kind;
  final String memberNumber;
  final String companyName;
  final String? companyAddress;
  final String? city;
  final String? district;
  final double? latitude;
  final double? longitude;
  final String? logo;
  final String defaultCurrency;
  final String status;
  final TenantPlan? plan;
  final int? maxMembers;
  final List<String> workflowOverrideStepKeys;

  bool get isLab => kind == TenantKind.lab;
  bool get isClinic => kind == TenantKind.clinic;
  bool get hasLocation => latitude != null && longitude != null;
  List<JobStep> get workflowOverrideSteps => workflowOverrideStepKeys
      .map(Job.parseStepValue)
      .where((step) => step.isLabOptional)
      .toList();
  String get locationLabel {
    final parts = [
      if ((district ?? '').trim().isNotEmpty) district!.trim(),
      if ((city ?? '').trim().isNotEmpty) city!.trim(),
    ];
    if (parts.isNotEmpty) return parts.join(' / ');
    return (companyAddress ?? '').trim();
  }

  factory Tenant.fromJson(Map<String, dynamic> j) => Tenant(
        id: j['id'] as String,
        kind: j['kind'] == 'lab' ? TenantKind.lab : TenantKind.clinic,
        memberNumber: (j['member_number'] as String?) ?? '',
        companyName: j['company_name'] as String,
        companyAddress: j['company_address'] as String?,
        city: j['city'] as String?,
        district: j['district'] as String?,
        latitude: (j['latitude'] as num?)?.toDouble(),
        longitude: (j['longitude'] as num?)?.toDouble(),
        logo: j['logo'] as String?,
        defaultCurrency: (j['default_currency'] as String?) ?? 'TRY',
        status: (j['status'] as String?) ?? 'active',
        plan: _parsePlan(j['plan'] as String?),
        maxMembers: (j['max_members'] as num?)?.toInt(),
        workflowOverrideStepKeys: j['workflow_overrides'] is List
            ? (j['workflow_overrides'] as List)
                .map((e) => e.toString())
                .toList()
            : const [],
      );

  static TenantPlan? _parsePlan(String? p) => switch (p) {
        'starter' => TenantPlan.starter,
        'pro' => TenantPlan.pro,
        'enterprise' => TenantPlan.enterprise,
        _ => null,
      };

  static TenantPlan parsePlanValue(String? value) =>
      _parsePlan(value) ?? TenantPlan.starter;
}

class TenantMembership {
  const TenantMembership({
    required this.id,
    required this.tenant,
    required this.role,
  });

  final String id;
  final Tenant tenant;
  final TenantRole role;

  // ── Access helpers ────────────────────────────────────────────────────────
  bool get isOwner => role == TenantRole.owner;
  bool get isAdmin => role == TenantRole.admin || role == TenantRole.owner;
  bool get canManageUsers =>
      role == TenantRole.owner || role == TenantRole.admin;
  bool get canManageJobs => role != TenantRole.finance;
  bool get canManageFinance =>
      role == TenantRole.owner ||
      role == TenantRole.admin ||
      role == TenantRole.finance ||
      role == TenantRole.member;
  bool get canManageProducts =>
      role == TenantRole.owner ||
      role == TenantRole.admin ||
      role == TenantRole.technician ||
      role == TenantRole.member;
  bool get canViewPatients =>
      role == TenantRole.owner ||
      role == TenantRole.admin ||
      role == TenantRole.doctor ||
      role == TenantRole.member;
  bool get canManageConnections =>
      role == TenantRole.owner ||
      role == TenantRole.admin ||
      role == TenantRole.member;

  // ── Fine-grained job actions ──────────────────────────────────────────────
  /// Can create new jobs (clinic side: owner/admin/doctor/member; not delivery/finance)
  bool get canCreateJobs =>
      role != TenantRole.delivery && role != TenantRole.finance;

  /// Can confirm physical delivery (delivery role + supervisors)
  bool get canDeliverJobs => role != TenantRole.finance;

  /// Can cancel or fully manage job lifecycle (not delivery-only or finance)
  bool get canCancelJobs =>
      role == TenantRole.owner ||
      role == TenantRole.admin ||
      role == TenantRole.member ||
      role == TenantRole.doctor;

  /// Primary focus is delivery — restrict to delivery-relevant UI
  bool get isDeliveryOnly => role == TenantRole.delivery;

  // ── Nav visibility ────────────────────────────────────────────────────────
  bool get showDashboard => true;
  bool get showJobs => canManageJobs;
  bool get showProducts => tenant.isLab && canManageProducts;
  bool get showPatients => tenant.isClinic && canViewPatients;
  bool get showConnections => canManageConnections;
  bool get showFinance => canManageFinance;

  factory TenantMembership.fromJson(Map<String, dynamic> j) {
    final expand = j['expand'] as Map<String, dynamic>?;
    final tenantData = expand?['tenant_id'] as Map<String, dynamic>?;
    return TenantMembership(
      id: j['id'] as String,
      tenant: Tenant.fromJson(tenantData!),
      role: parseRole(j['role'] as String),
    );
  }

  static TenantRole parseRole(String r) => switch (r) {
        'owner' => TenantRole.owner,
        'admin' => TenantRole.admin,
        'technician' => TenantRole.technician,
        'delivery' => TenantRole.delivery,
        'finance' => TenantRole.finance,
        'doctor' => TenantRole.doctor,
        _ => TenantRole.member,
      };

  String get roleLabel => switch (role) {
        TenantRole.owner => 'Sahibi',
        TenantRole.admin => 'Yönetici',
        TenantRole.technician => 'Teknisyen',
        TenantRole.delivery => 'Teslimat Elemanı',
        TenantRole.finance => 'Finans Elemanı',
        TenantRole.doctor => 'Hekim',
        TenantRole.member => 'Üye',
      };
}
