<?php

namespace Kylin\Pet\Services;

use App\Models\Boarding;
use App\Models\BoardingLog;
use Illuminate\Support\Facades\DB;
use Kylin\Pet\Enums\BoardingStatus;

/**
 * 寄养服务 - 业务逻辑层
 * 处理寄养登记、入住、退房、照护日志
 * 合规要求：GB/T 45204-2025 消毒记录管理
 */
class BoardingService
{
    /**
     * 创建寄养预约（含消毒记录）
     */
    public function create(array $data): Boarding
    {
        return DB::transaction(function () use ($data) {
            // GB/T 45204 要求：入住前必须记录消毒信息
            if (empty($data['disinfection_record'])) {
                throw new \InvalidArgumentException('入住前消毒记录为必填项（GB/T 45204-2025）');
            }

            $data['status'] = BoardingStatus::RESERVED->value;
            $boarding = Boarding::create($data);

            $this->audit('boarding_created', $boarding, [
                'pet_id' => $boarding->pet_id,
                'disinfection_record' => true,
            ]);

            return $boarding;
        });
    }

    /**
     * 办理入住
     */
    public function checkIn(Boarding $boarding): Boarding
    {
        return DB::transaction(function () use ($boarding) {
            $boarding->update([
                'status' => BoardingStatus::CHECKED_IN->value,
                'started_at' => now(),
            ]);

            $this->audit('boarding_check_in', $boarding, ['pet_id' => $boarding->pet_id]);

            return $boarding->fresh();
        });
    }

    /**
     * 办理退房
     */
    public function checkOut(Boarding $boarding): Boarding
    {
        return DB::transaction(function () use ($boarding) {
            $endedAt = now();
            $startedAt = Carbon::parse($boarding->started_at);
            $days = $startedAt->diffInDays($endedAt) + 1;

            $boarding->update([
                'status' => BoardingStatus::COMPLETED->value,
                'ended_at' => $endedAt,
            ]);

            $this->audit('boarding_check_out', $boarding, [
                'pet_id' => $boarding->pet_id,
                'days' => $days,
            ]);

            return $boarding->fresh();
        });
    }

    /**
     * 添加照护日志
     * NY/T 4659 要求：每日填写照护记录
     */
    public function addDailyLog(array $data): BoardingLog
    {
        $log = BoardingLog::create($data);

        $this->audit('boarding_log_added', null, [
            'boarding_id' => $data['boarding_id'] ?? null,
            'log_date' => $data['log_date'] ?? null,
        ]);

        return $log;
    }

    /**
     * 获取寄养照护日志
     */
    public function getBoardingLogs(int $boardingId): array
    {
        return BoardingLog::where('boarding_id', $boardingId)
            ->orderBy('log_date', 'desc')
            ->get()
            ->toArray();
    }

    /**
     * 记录寄养审计日志
     *
     * 依据《动物防疫法》和 GB/T 45204-2025，
     * 寄养登记、入住、退房、照护日志等操作需记录审计日志。
     */
    private function audit(string $event, ?Boarding $boarding, array $extra = []): void
    {
        if (! class_exists(\Kylin\AuditLog\Models\AuditLog::class)) {
            return;
        }

        try {
            \Kylin\AuditLog\Models\AuditLog::create([
                'event' => $event,
                'model_type' => Boarding::class,
                'model_id' => $boarding?->id ?? 0,
                'new_values' => $extra,
                'old_values' => null,
                'user_id' => auth()->id(),
                'ip' => request()?->ip(),
                'url' => request()?->fullUrl(),
                'tag' => 'pet-boarding',
            ]);
        } catch (\Throwable $e) {
            logger()->warning('寄养审计日志写入失败', [
                'error' => $e->getMessage(),
                'boarding_id' => $boarding?->id,
                'event' => $event,
            ]);
        }
    }
}
