<?php

/**
 * 文件功能：五子棋对局模型
 *
 * 管理 PvP（玩家对战）和 PvE（人机对战）两种模式的对局记录。
 * 提供棋盘操作、胜负判断及状态管理方法。
 *
 * @author  ChatRoom Laravel
 *
 * @version 1.0.0
 */

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;

class GomokuGame extends Model
{
    protected $fillable = [
        'mode',
        'room_id',
        'player_black_id',
        'player_white_id',
        'ai_level',
        'status',
        'board',
        'current_turn',
        'winner',
        'moves_history',
        'reward_gold',
        'entry_fee',
        'invite_expires_at',
        'started_at',
        'finished_at',
    ];

    /**
     * 属性类型转换。
     */
    protected function casts(): array
    {
        return [
            'board' => 'array',
            'moves_history' => 'array',
            'invite_expires_at' => 'datetime',
            'started_at' => 'datetime',
            'finished_at' => 'datetime',
        ];
    }

    // ─── 关联 ─────────────────────────────────────────────────────────

    /**
     * 黑棋玩家（发起方）。
     */
    public function playerBlack(): BelongsTo
    {
        return $this->belongsTo(User::class, 'player_black_id');
    }

    /**
     * 白棋玩家（PvP 接受方）。
     */
    public function playerWhite(): BelongsTo
    {
        return $this->belongsTo(User::class, 'player_white_id');
    }

    /**
     * 所属聊天室。
     */
    public function room(): BelongsTo
    {
        return $this->belongsTo(Room::class);
    }

    // ─── 棋盘操作 ─────────────────────────────────────────────────────

    /**
     * 生成空白 15×15 棋盘（全 0）。
     */
    public static function emptyBoard(): array
    {
        return array_fill(0, 15, array_fill(0, 15, 0));
    }

    /**
     * 在指定坐标落子，返回新棋盘状态。
     *
     * @param  array  $board  当前棋盘
     * @param  int  $row  行（0-14）
     * @param  int  $col  列（0-14）
     * @param  int  $color  棋子颜色（1=黑 2=白）
     */
    public static function placeStone(array $board, int $row, int $col, int $color): array
    {
        $board[$row][$col] = $color;

        return $board;
    }

    /**
     * 检查指定坐标是否已有棋子。
     *
     * @param  array  $board  棋盘
     * @param  int  $row  行
     * @param  int  $col  列
     */
    public static function isOccupied(array $board, int $row, int $col): bool
    {
        return ($board[$row][$col] ?? 0) !== 0;
    }

    /**
     * 判断在指定坐标落子后，该颜色是否已连成五子。
     *
     * @param  array  $board  落子后的棋盘
     * @param  int  $row  最后落子行
     * @param  int  $col  最后落子列
     * @param  int  $color  棋子颜色（1=黑 2=白）
     */
    public static function checkWin(array $board, int $row, int $col, int $color): bool
    {
        // 四个方向：横、竖、左斜、右斜
        $directions = [[0, 1], [1, 0], [1, 1], [1, -1]];

        foreach ($directions as [$dr, $dc]) {
            $count = 1;

            // 向正方向延伸
            for ($i = 1; $i <= 4; $i++) {
                $r = $row + $dr * $i;
                $c = $col + $dc * $i;
                if ($r < 0 || $r >= 15 || $c < 0 || $c >= 15) {
                    break;
                }
                if (($board[$r][$c] ?? 0) !== $color) {
                    break;
                }
                $count++;
            }

            // 向反方向延伸
            for ($i = 1; $i <= 4; $i++) {
                $r = $row - $dr * $i;
                $c = $col - $dc * $i;
                if ($r < 0 || $r >= 15 || $c < 0 || $c >= 15) {
                    break;
                }
                if (($board[$r][$c] ?? 0) !== $color) {
                    break;
                }
                $count++;
            }

            if ($count >= 5) {
                return true;
            }
        }

        return false;
    }

    /**
     * 判断棋盘是否已下满（平局）。
     *
     * @param  array  $board  棋盘
     */
    public static function isBoardFull(array $board): bool
    {
        foreach ($board as $row) {
            foreach ($row as $cell) {
                if ($cell === 0) {
                    return false;
                }
            }
        }

        return true;
    }

    // ─── 状态辅助 ─────────────────────────────────────────────────────

    /**
     * 判断对局是否属于某个用户。
     *
     * @param  int  $userId  用户 ID
     */
    public function belongsToUser(int $userId): bool
    {
        return $this->player_black_id === $userId
            || $this->player_white_id === $userId;
    }

    /**
     * 获取指定用户在此对局的棋子颜色。
     * 返回 1（黑棋）或 2（白棋），不在局中返回 null。
     *
     * @param  int  $userId  用户 ID
     */
    public function colorOf(int $userId): ?int
    {
        if ($this->player_black_id === $userId) {
            return 1;
        }
        if ($this->player_white_id === $userId) {
            return 2;
        }

        return null;
    }

    /**
     * 判断当前是否轮到指定用户行棋（PvP 用）。
     *
     * @param  int  $userId  用户 ID
     */
    public function isUserTurn(int $userId): bool
    {
        return $this->colorOf($userId) === $this->current_turn;
    }
}
