import '../../features/shared/job_files_repository.dart';
import '../../features/shared/tenant_team_repository.dart';
import '../../models/job_file.dart';
import '../../models/tenant.dart';
import '../api/pocketbase_client.dart';

// ── Message segments ──────────────────────────────────────────────────────────

sealed class MessageSegment {}

class TextSegment extends MessageSegment {
  TextSegment(this.text);
  final String text;
}

class ActionSegment extends MessageSegment {
  ActionSegment(this.action);
  final AiAction action;
}

// ── Action model ──────────────────────────────────────────────────────────────

class AiAction {
  const AiAction({
    required this.type,
    required this.params,
    required this.label,
  });
  final String type;
  final Map<String, String> params;
  final String label;

  bool get isDangerous => type == 'cancel_job';
  bool get isFileAction => type == 'job_files';
}

// ── Action outcome ────────────────────────────────────────────────────────────

sealed class ActionOutcome {}

class ActionSuccess extends ActionOutcome {
  ActionSuccess(this.message);
  final String message;
}

class ActionError extends ActionOutcome {
  ActionError(this.error);
  final String error;
}

class ActionFiles extends ActionOutcome {
  ActionFiles(this.files);
  final List<JobFile> files;
}

// ── Parser ────────────────────────────────────────────────────────────────────

List<MessageSegment> parseSegments(String text) {
  // Strip code fences wrapping <dls-action> tags that the AI sometimes emits.
  // Handles: ```xml\n<dls-action .../>\n```  and  ```\n<dls-action .../>\n```
  text = text.replaceAllMapped(
    RegExp(r'```(?:xml)?\s*\n(\s*<dls-action\s[^>]*/>)\s*\n\s*```'),
    (m) => m.group(1)!,
  );
  // Also handle inline variant: ```xml <dls-action .../> ```
  text = text.replaceAllMapped(
    RegExp(r'```(?:xml)?\s*(<dls-action\s[^>]*/>)\s*```'),
    (m) => m.group(1)!,
  );

  final pattern = RegExp(r'<dls-action\s([^/]*?)/>', dotAll: true);
  final segments = <MessageSegment>[];
  int last = 0;

  for (final m in pattern.allMatches(text)) {
    final before = text.substring(last, m.start).trim();
    if (before.isNotEmpty) segments.add(TextSegment(before));

    final attrs = _parseAttrs(m.group(1) ?? '');
    segments.add(ActionSegment(AiAction(
      type: attrs['type'] ?? '',
      params: attrs,
      label: attrs['label'] ?? attrs['type'] ?? 'İşlem',
    )));
    last = m.end;
  }

  final rest = text.substring(last).trim();
  if (rest.isNotEmpty) segments.add(TextSegment(rest));
  return segments;
}

Map<String, String> _parseAttrs(String s) {
  final result = <String, String>{};
  for (final m in RegExp(r'(\w+)="([^"]*)"').allMatches(s)) {
    result[m.group(1)!] = m.group(2)!;
  }
  return result;
}

// ── Executor ──────────────────────────────────────────────────────────────────

class AiActionExecutor {
  static final _pb = PocketBaseClient.instance.pb;

  static Future<ActionOutcome> execute(
    AiAction action,
    TenantMembership membership,
  ) async {
    try {
      return switch (action.type) {
        'cancel_job'     => await _cancelJob(action.params),
        'mark_delivered' => await _markDelivered(action.params),
        'job_files'      => await _jobFiles(action.params),
        'add_member'     => await _addMember(action.params, membership),
        _                => ActionError('Bilinmeyen işlem türü: ${action.type}'),
      };
    } catch (e) {
      final msg = e.toString();
      if (msg.length > 120) return ActionError('Sunucu hatası');
      return ActionError(msg);
    }
  }

  static Future<ActionOutcome> _cancelJob(Map<String, String> p) async {
    final id = p['job_id'];
    if (id == null || id.isEmpty) return ActionError('İş ID bulunamadı.');
    await _pb.collection('jobs').update(id, body: {'status': 'cancelled'});
    return ActionSuccess('İş başarıyla iptal edildi.');
  }

  static Future<ActionOutcome> _markDelivered(Map<String, String> p) async {
    final id = p['job_id'];
    if (id == null || id.isEmpty) return ActionError('İş ID bulunamadı.');
    await _pb.collection('jobs').update(id, body: {'status': 'delivered'});
    return ActionSuccess('İş teslim edildi olarak işaretlendi.');
  }

  static Future<ActionOutcome> _jobFiles(Map<String, String> p) async {
    final id = p['job_id'];
    if (id == null || id.isEmpty) return ActionError('İş ID bulunamadı.');
    final files = await JobFilesRepository.instance.listForJob(id);
    if (files.isEmpty) return ActionSuccess('Bu iş için henüz dosya yüklenmemiş.');
    return ActionFiles(files);
  }

  static Future<ActionOutcome> _addMember(
    Map<String, String> p,
    TenantMembership membership,
  ) async {
    final email     = p['email'];
    final firstName = p['first_name'];
    final lastName  = p['last_name'] ?? '';
    final role      = p['role'];
    final password  = p['password'];

    if (email == null || firstName == null || role == null || password == null) {
      return ActionError('Eksik bilgi: e-posta, ad, rol ve şifre gerekli.');
    }

    await TenantTeamRepository.instance.addMember(
      tenantId:  membership.tenant.id,
      email:     email,
      password:  password,
      firstName: firstName,
      lastName:  lastName,
      role:      TenantMembership.parseRole(role),
    );
    return ActionSuccess('$firstName $lastName ekibe eklendi.');
  }
}
