<?php
namespace Site\Lib;

class DiffViewer {
  private $diffContent;

  public function __construct(string $filePath) {
    if (!file_exists($filePath)) {
      throw new \Exception("Diff file not found: $filePath");
    }
    $this->diffContent = file_get_contents($filePath);
  }

  public function displaySideBySide(): string {
    $lines = explode("\n", $this->diffContent);
    $fileDiffs = [];
    $currentFile = null;
    $hunk = [];
    $lineNumbers = ['left' => 0, 'right' => 0];
    $currentLeftLines = [];
    $currentRightLines = [];

    foreach ($lines as $line) {
      // ファイルヘッダーの処理
      if (preg_match('/^---\s+(.+)/', $line, $matches)) {
        // ファイルを処理する場合、データを保存する
        if ($currentFile !== null) {
          $this->processHunk($hunk, $currentLeftLines, $currentRightLines, $lineNumbers);
          $fileDiffs[$currentFile] = [
            'leftLines' => $currentLeftLines,
            'rightLines' => $currentRightLines
          ];
          $hunk = [];
          $currentLeftLines = [];
          $currentRightLines = [];
          $lineNumbers = ['left' => 0, 'right' => 0];
        }
        $currentFile = $matches[1];
        continue;
      }
      if (preg_match('/^\+\+\+\s+(.+)/', $line)) {
        continue;
      }

      // ハンクヘッダーの処理 (例：@@ -10,6 +10,7 @@)
      if (preg_match('/^@@\s+-(\d+),\d+\s+\+(\d+),\d+\s+@@/', $line, $matches)) {
        $this->processHunk($hunk, $currentLeftLines, $currentRightLines, $lineNumbers);
        $hunk = [];
        $lineNumbers['left'] = (int)$matches[1];
        $lineNumbers['right'] = (int)$matches[2];
        continue;
      }

      // ハンクでの行列の集まり
      if (substr($line, 0, 1) === '-' || substr($line, 0, 1) === '+' || substr($line, 0, 1) === ' ') {
        $hunk[] = $line;
      }
    }

    // 最後のハンク・ファイルの処理
    if ($currentFile !== null) {
      $this->processHunk($hunk, $currentLeftLines, $currentRightLines, $lineNumbers);
      $fileDiffs[$currentFile] = [
        'leftLines' => $currentLeftLines,
        'rightLines' => $currentRightLines
      ];
    }

    // 各ファイルにHTMLの出力の作成
    $html = '';
    foreach ($fileDiffs as $fileName => $diff) {
      $html .= "\n        <h2>ファイル： ".htmlspecialchars($fileName)."</h2>\n";
      $html .= $this->generateHtml($diff['leftLines'], $diff['rightLines']);
    }

    return $html;
  }

  private function processHunk(array $hunk, array &$leftLines, array &$rightLines, array &$lineNumbers): void {
    foreach ($hunk as $line) {
      $prefix = substr($line, 0, 1);
      $content = substr($line, 1);

      if ($prefix === '-') {
        $leftLines[] = ['content' => htmlspecialchars($content), 'type' => 'removed', 'line' => $lineNumbers['left']];
        $lineNumbers['left']++;
      } elseif ($prefix === '+') {
        $rightLines[] = ['content' => htmlspecialchars($content), 'type' => 'added', 'line' => $lineNumbers['right']];
        $lineNumbers['right']++;
      } elseif ($prefix === ' ') {
        // 両側のコンテキストは同じ行列があるかの確認
        while ($lineNumbers['left'] < $lineNumbers['right']) {
          $leftLines[] = ['content' => '', 'type' => 'empty', 'line' => $lineNumbers['left']];
          $lineNumbers['left']++;
        }
        while ($lineNumbers['right'] < $lineNumbers['left']) {
          $rightLines[] = ['content' => '', 'type' => 'empty', 'line' => $lineNumbers['right']];
          $lineNumbers['right']++;
        }
        $leftLines[] = ['content' => htmlspecialchars($content), 'type' => 'context', 'line' => $lineNumbers['left']];
        $rightLines[] = ['content' => htmlspecialchars($content), 'type' => 'context', 'line' => $lineNumbers['right']];
        $lineNumbers['left']++;
        $lineNumbers['right']++;
      }
    }
  }

  private function generateHtml(array $leftLines, array $rightLines): string {
    $html = "        <p>\n          <table class=\"diff-table\">\n";
    $html .= "            <tr class=\"diff-header\"><th colspan=\"2\">前</th><th colspan=\"2\">新</th></tr>\n";

    $maxLines = max(count($leftLines), count($rightLines));
    for ($i = 0; $i < $maxLines; $i++) {
      $left = isset($leftLines[$i]) ? $leftLines[$i] : ['content' => '', 'type' => 'empty', 'line' => ''];
      $right = isset($rightLines[$i]) ? $rightLines[$i] : ['content' => '', 'type' => 'empty', 'line' => ''];

      $html .= "          <tr>\n";
      // 左（変更前）
      $html .= "            <td class=\"line-number\">".($left['line'] ?: '&nbsp;')."</td>\n";
      $html .= "            <td class=\"{$left['type']}\">".($left['content'] ?: '&nbsp;')."</td>\n";
      // 右（変更後）
      $html .= "            <td class=\"line-number\">".($right['line'] ?: '&nbsp;')."</td>\n";
      $html .= "            <td class=\"{$right['type']}\">".($right['content'] ?: '&nbsp;')."</td>\n";
      $html .= "          </tr>\n";
    }

    $html .= "          </table>\n        </p>\n";
    return $html;
  }
}