<?php
// app/controllers/debug.php

declare(strict_types=1);

use ScMedia\Http\Response;
use ScMedia\Http\Router;

final class DebugController extends BaseController {
  public static function register(Router $router, Container $container): void {
    $self = new self($container);
    $router->add('POST', '/api/debug/event', fn() => $self->debugEvent());
    $router->add('GET', '/api/debug/stats', fn() => $self->stats());
    $router->add('GET', '/api/debug/db-tables', fn() => $self->dbTables());
    $router->add('GET', '/api/debug/db-table', fn() => $self->dbTable());
    $router->add('POST', '/api/debug/clear-content', fn() => $self->clearContent());
    $router->add('POST', '/api/debug/clear-index', fn() => $self->clearIndex());
    $router->add('POST', '/api/debug/reset-db', fn() => $self->resetDb());
    $router->add('GET', '/api/debug/db-dump', fn() => $self->dbDump());
    $router->add('POST', '/api/debug/db-restore', fn() => $self->dbRestore());
    $router->add('GET', '/api/debug/mkvmerge-check', fn() => $self->mkvmergeCheck());
  }

  private function debugEvent(): void {
    require_debug($this->config(), false);
    $logger = $this->logger();
    $body = read_json_body();
    $name = (string)($body['name'] ?? 'debug');
    $payload = is_array($body['payload'] ?? null) ? $body['payload'] : [];
    $logger->log('debug', 'Debug event', ['name' => $name, 'payload' => $payload]);
    Response::json(['ok' => true, 'data' => ['name' => $name]]);
  }

  private function stats(): void {
    require_debug($this->config(), false);
    $logger = $this->logger();

    try {
      $schema = $this->services()['schema'];
      $content = $schema->getContentStats();
      $db = $schema->getDbStats();
      $dbInfo = $schema->getDbInfo();
      Response::json(['ok' => true, 'data' => ['content' => $content, 'db' => $db, 'db_info' => $dbInfo]]);
    } catch (Throwable $e) {
      $logger->log('error', 'Debug stats failed', ['error' => $e->getMessage()]);
      Response::json(['ok' => false, 'error' => ['code' => 'STATS_FAILED', 'message' => $e->getMessage()]], 500);
    }
  }

  private function dbTables(): void {
    require_debug($this->config(), false);
    $logger = $this->logger();
    try {
      $items = $this->services()['schema']->listTablesWithCounts();
      Response::json(['ok' => true, 'data' => ['items' => $items]]);
    } catch (Throwable $e) {
      $logger->log('error', 'Debug db tables failed', ['error' => $e->getMessage()]);
      Response::json(['ok' => false, 'error' => ['code' => 'DB_TABLES_FAILED', 'message' => $e->getMessage()]], 500);
    }
  }

  private function dbTable(): void {
    require_debug($this->config(), false);
    $logger = $this->logger();
    $name = (string)($_GET['name'] ?? '');
    $limit = isset($_GET['limit']) ? (int)$_GET['limit'] : 50;
    try {
      $data = $this->services()['schema']->fetchTableRows($name, $limit);
      Response::json(['ok' => true, 'data' => $data]);
    } catch (Throwable $e) {
      $logger->log('error', 'Debug db table preview failed', ['error' => $e->getMessage()]);
      Response::json(['ok' => false, 'error' => ['code' => 'DB_TABLE_FAILED', 'message' => $e->getMessage()]], 500);
    }
  }

  private function clearContent(): void {
    require_debug($this->config(), false);
    $logger = $this->logger();

    $body = read_json_body();
    if ((string)($body['confirm'] ?? '') !== 'CLEAR CONTENT') {
      $logger->log('warn', 'Clear content denied: bad confirmation');
      Response::json(['ok' => false, 'error' => ['code' => 'CONFIRM_REQUIRED', 'message' => 'Type CLEAR CONTENT']], 400);
      return;
    }

    try {
      $this->services()['schema']->clearContent();
      $logger->log('warn', 'Content cleared');
      Response::json(['ok' => true, 'data' => ['reload' => true]]);
    } catch (Throwable $e) {
      $logger->log('error', 'Clear content failed', ['error' => $e->getMessage()]);
      Response::json(['ok' => false, 'error' => ['code' => 'CLEAR_FAILED', 'message' => $e->getMessage()]], 500);
    }
  }

  private function clearIndex(): void {
    require_debug($this->config(), false);
    $logger = $this->logger();

    $body = read_json_body();
    if ((string)($body['confirm'] ?? '') !== 'CLEAR') {
      $logger->log('warn', 'Clear index denied: bad confirmation');
      Response::json(['ok' => false, 'error' => ['code' => 'CONFIRM_REQUIRED', 'message' => 'Type CLEAR']], 400);
      return;
    }

    try {
      $this->services()['schema']->clearIndex();
      $logger->log('info', 'Index cleared');
      Response::json(['ok' => true]);
    } catch (Throwable $e) {
      $logger->log('error', 'Clear index failed', ['error' => $e->getMessage()]);
      Response::json(['ok' => false, 'error' => ['code' => 'CLEAR_FAILED', 'message' => $e->getMessage()]], 500);
    }
  }

  private function resetDb(): void {
    require_debug($this->config(), true);
    $logger = $this->logger();

    $body = read_json_body();
    if ((string)($body['confirm'] ?? '') !== 'RESET DATABASE') {
      $logger->log('warn', 'Reset DB denied: bad confirmation');
      Response::json(['ok' => false, 'error' => ['code' => 'CONFIRM_REQUIRED', 'message' => 'Type RESET DATABASE']], 400);
      return;
    }

    try {
      $log = $this->services()['schema']->resetDatabase();
      $logger->log('warn', 'Database reset', ['log' => $log]);
      Response::json(['ok' => true, 'data' => ['log' => $log, 'reload' => true]]);
    } catch (Throwable $e) {
      $logger->log('error', 'Reset DB failed', ['error' => $e->getMessage()]);
      Response::json(['ok' => false, 'error' => ['code' => 'RESET_FAILED', 'message' => $e->getMessage()]], 500);
    }
  }

  private function dbDump(): void {
    require_debug($this->config(), false);
    $logger = $this->logger();
    try {
      $sql = $this->services()['schema']->dumpDatabase();
      $filename = 'scmedia_dump_' . date('Ymd_His') . '.sql';
      header('Content-Type: application/sql; charset=utf-8');
      header('Content-Disposition: attachment; filename="' . $filename . '"');
      echo $sql;
    } catch (Throwable $e) {
      $logger->log('error', 'DB dump failed', ['error' => $e->getMessage()]);
      Response::json(['ok' => false, 'error' => ['code' => 'DUMP_FAILED', 'message' => $e->getMessage()]], 500);
    }
  }

  private function dbRestore(): void {
    require_debug($this->config(), true);
    $logger = $this->logger();

    $body = read_json_body();
    if ((string)($body['confirm'] ?? '') !== 'RESTORE DATABASE') {
      $logger->log('warn', 'Restore DB denied: bad confirmation');
      Response::json(['ok' => false, 'error' => ['code' => 'CONFIRM_REQUIRED', 'message' => 'Type RESTORE DATABASE']], 400);
      return;
    }
    $sql = (string)($body['sql'] ?? '');
    if (trim($sql) === '') {
      Response::json(['ok' => false, 'error' => ['code' => 'SQL_REQUIRED', 'message' => 'SQL required']], 400);
      return;
    }

    try {
      $log = $this->services()['schema']->restoreDatabaseFromSql($sql);
      $logger->log('warn', 'Database restored', ['log' => $log]);
      Response::json(['ok' => true, 'data' => ['log' => $log, 'reload' => true]]);
    } catch (Throwable $e) {
      $logger->log('error', 'Restore DB failed', ['error' => $e->getMessage()]);
      Response::json(['ok' => false, 'error' => ['code' => 'RESTORE_FAILED', 'message' => $e->getMessage()]], 500);
    }
  }

  private function mkvmergeCheck(): void {
    require_debug($this->config(), false);
    $logger = $this->logger();
    $path = (string)($_GET['path'] ?? '');
    if ($path === '') {
      Response::json(['ok' => false, 'error' => ['code' => 'PATH_REQUIRED', 'message' => 'path required']], 400);
      return;
    }

    $shell = $this->services()['shell'] ?? null;
    $bin = ($shell instanceof \ScMedia\Services\ShellTool) ? ($shell->which('mkvmerge') ?? '') : '';
    if ($bin === '') {
      $logger->log('warn', 'mkvmerge check failed: binary not found');
      Response::json(['ok' => false, 'error' => ['code' => 'NO_MKVMERGE', 'message' => 'mkvmerge not found']]);
      return;
    }

    $cmdBase = $bin . ' -J ' . escapeshellarg($path) . ' 2>/dev/null';
    $out = ($shell instanceof \ScMedia\Services\ShellTool) ? $shell->exec($cmdBase) : null;
    if (!is_string($out) || $out === '') {
      $logger->log('warn', 'mkvmerge check returned empty output', ['path' => $path]);
      Response::json(['ok' => true, 'data' => ['bin' => $bin, 'output' => null]]);
      return;
    }

    $json = json_decode($out, true);
    if (!is_array($json)) {
      $logger->log('warn', 'mkvmerge check failed: bad json', ['path' => $path]);
      Response::json(['ok' => false, 'error' => ['code' => 'BAD_JSON', 'message' => 'invalid mkvmerge json']], 400);
      return;
    }

    Response::json(['ok' => true, 'data' => ['bin' => $bin, 'output' => $json]]);
  }
}
