<?php

declare(strict_types=1);

namespace App\Controller\Api\V1;

use App\Controller\AbstractController;
use App\Middleware\AuthMiddleware;
use App\Middleware\PermissionMiddleware;
use App\Service\DashboardStatsService;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\Middleware;
use Hyperf\HttpServer\Annotation\RequestMapping;
use OpenApi\Attributes as OA;
use Psr\Http\Message\ResponseInterface;

/**
 * Dashboard 统计接口
 *
 * 提供 overview / trend / breakdown 三类数据同步统计端点
 */
#[OA\Tag(name: 'Dashboard', description: 'Dashboard 数据同步统计')]
#[Controller(prefix: "/api/v1/dashboard")]
#[Middleware(AuthMiddleware::class)]
#[Middleware(PermissionMiddleware::class)]
class DashboardController extends AbstractController
{
    public function __construct(
        protected readonly DashboardStatsService $statsService,
    ) {}

    /**
     * 概览统计
     */
    #[OA\Get(
        path: '/dashboard/overview',
        summary: '获取概览统计',
        description: '返回今日/本周/本月的成功和失败同步数，以及按数据类型的本月分组统计。',
        security: [['bearerAuth' => []]],
        tags: ['Dashboard'],
        responses: [
            new OA\Response(
                response: 200,
                description: '获取成功',
                content: new OA\JsonContent(properties: [
                    new OA\Property(property: 'code', type: 'integer', example: 0),
                    new OA\Property(property: 'message', type: 'string', example: '获取成功'),
                    new OA\Property(property: 'data', ref: '#/components/schemas/DashboardOverview'),
                ])
            ),
            new OA\Response(response: 401, description: '未认证', content: new OA\JsonContent(ref: '#/components/schemas/ErrorResponse')),
            new OA\Response(response: 403, description: '无权限', content: new OA\JsonContent(ref: '#/components/schemas/ErrorResponse')),
        ]
    )]
    #[RequestMapping(path: "overview", methods: "GET")]
    public function overview(): ResponseInterface|array
    {
        $scope_type = $this->request->getAttribute('scope_type', 'all');
        $scope_ids = $this->request->getAttribute('scope_ids', []);

        $data = $this->statsService->getOverview($scope_type, $scope_ids);

        return [
            'code' => 0,
            'message' => '获取成功',
            'data' => $data,
        ];
    }

    /**
     * 趋势数据
     */
    #[OA\Get(
        path: '/dashboard/trend',
        summary: '获取趋势数据',
        description: '返回指定时间范围内按日/周/月聚合的成功和失败同步趋势。',
        security: [['bearerAuth' => []]],
        tags: ['Dashboard'],
        parameters: [
            new OA\Parameter(name: 'from', in: 'query', required: false, description: '起始日期（默认30天前）', schema: new OA\Schema(type: 'string', format: 'date', example: '2026-02-15')),
            new OA\Parameter(name: 'to', in: 'query', required: false, description: '结束日期（默认今天）', schema: new OA\Schema(type: 'string', format: 'date', example: '2026-03-17')),
            new OA\Parameter(name: 'group_by', in: 'query', required: false, description: '聚合粒度', schema: new OA\Schema(type: 'string', enum: ['day', 'week', 'month'], default: 'day')),
            new OA\Parameter(name: 'data_type', in: 'query', required: false, description: '数据类型筛选', schema: new OA\Schema(type: 'string', enum: ['order', 'product', 'refund', 'inventory'])),
        ],
        responses: [
            new OA\Response(
                response: 200,
                description: '获取成功',
                content: new OA\JsonContent(properties: [
                    new OA\Property(property: 'code', type: 'integer', example: 0),
                    new OA\Property(property: 'message', type: 'string', example: '获取成功'),
                    new OA\Property(property: 'data', type: 'array', items: new OA\Items(ref: '#/components/schemas/DashboardTrendItem')),
                ])
            ),
            new OA\Response(response: 400, description: '参数错误', content: new OA\JsonContent(ref: '#/components/schemas/ErrorResponse')),
            new OA\Response(response: 401, description: '未认证', content: new OA\JsonContent(ref: '#/components/schemas/ErrorResponse')),
            new OA\Response(response: 403, description: '无权限', content: new OA\JsonContent(ref: '#/components/schemas/ErrorResponse')),
        ]
    )]
    #[RequestMapping(path: "trend", methods: "GET")]
    public function trend(): ResponseInterface|array
    {
        $from = $this->request->input('from', date('Y-m-d', strtotime('-30 days')));
        $to = $this->request->input('to', date('Y-m-d'));
        $group_by = $this->request->input('group_by', 'day');
        $data_type = $this->request->input('data_type');

        // 校验 group_by
        if (!in_array($group_by, DashboardStatsService::VALID_GROUP_BY, true)) {
            return $this->response->json([
                'code' => 400,
                'message' => "无效的 group_by 参数: {$group_by}，可选值: " . implode(', ', DashboardStatsService::VALID_GROUP_BY),
                'data' => null,
            ])->withStatus(400);
        }

        // 校验 data_type
        if ($data_type !== null && !in_array($data_type, DashboardStatsService::VALID_DATA_TYPES, true)) {
            return $this->response->json([
                'code' => 400,
                'message' => "无效的 data_type 参数: {$data_type}，可选值: " . implode(', ', DashboardStatsService::VALID_DATA_TYPES),
                'data' => null,
            ])->withStatus(400);
        }

        // 校验日期格式
        if (!$this->isValidDate($from) || !$this->isValidDate($to)) {
            return $this->response->json([
                'code' => 400,
                'message' => '无效的日期格式，请使用 YYYY-MM-DD',
                'data' => null,
            ])->withStatus(400);
        }

        // 校验 from <= to
        if ($from > $to) {
            return $this->response->json([
                'code' => 400,
                'message' => 'from 日期不能晚于 to 日期',
                'data' => null,
            ])->withStatus(400);
        }

        $scope_type = $this->request->getAttribute('scope_type', 'all');
        $scope_ids = $this->request->getAttribute('scope_ids', []);

        $data = $this->statsService->getTrend($from, $to, $group_by, $data_type, $scope_type, $scope_ids);

        return [
            'code' => 0,
            'message' => '获取成功',
            'data' => $data,
        ];
    }

    /**
     * 分组统计
     */
    #[OA\Get(
        path: '/dashboard/breakdown',
        summary: '获取分组统计',
        description: '按公司/平台/店铺维度统计成功和失败同步数。',
        security: [['bearerAuth' => []]],
        tags: ['Dashboard'],
        parameters: [
            new OA\Parameter(name: 'dimension', in: 'query', required: true, description: '分组维度', schema: new OA\Schema(type: 'string', enum: ['company', 'platform', 'store'])),
            new OA\Parameter(name: 'from', in: 'query', required: false, description: '起始日期（默认今天）', schema: new OA\Schema(type: 'string', format: 'date', example: '2026-03-17')),
            new OA\Parameter(name: 'to', in: 'query', required: false, description: '结束日期（默认今天）', schema: new OA\Schema(type: 'string', format: 'date', example: '2026-03-17')),
            new OA\Parameter(name: 'data_type', in: 'query', required: false, description: '数据类型筛选', schema: new OA\Schema(type: 'string', enum: ['order', 'product', 'refund', 'inventory'])),
        ],
        responses: [
            new OA\Response(
                response: 200,
                description: '获取成功',
                content: new OA\JsonContent(properties: [
                    new OA\Property(property: 'code', type: 'integer', example: 0),
                    new OA\Property(property: 'message', type: 'string', example: '获取成功'),
                    new OA\Property(property: 'data', type: 'array', items: new OA\Items(ref: '#/components/schemas/DashboardBreakdownItem')),
                ])
            ),
            new OA\Response(response: 400, description: '参数错误', content: new OA\JsonContent(ref: '#/components/schemas/ErrorResponse')),
            new OA\Response(response: 401, description: '未认证', content: new OA\JsonContent(ref: '#/components/schemas/ErrorResponse')),
            new OA\Response(response: 403, description: '无权限', content: new OA\JsonContent(ref: '#/components/schemas/ErrorResponse')),
        ]
    )]
    #[RequestMapping(path: "breakdown", methods: "GET")]
    public function breakdown(): ResponseInterface|array
    {
        $dimension = $this->request->input('dimension');

        // 校验 dimension 必填
        if ($dimension === null || $dimension === '') {
            return $this->response->json([
                'code' => 400,
                'message' => '缺少必填参数: dimension',
                'data' => null,
            ])->withStatus(400);
        }

        // 校验 dimension 枚举
        if (!in_array($dimension, DashboardStatsService::VALID_DIMENSIONS, true)) {
            return $this->response->json([
                'code' => 400,
                'message' => "无效的 dimension 参数: {$dimension}，可选值: " . implode(', ', DashboardStatsService::VALID_DIMENSIONS),
                'data' => null,
            ])->withStatus(400);
        }

        $from = $this->request->input('from', date('Y-m-d'));
        $to = $this->request->input('to', date('Y-m-d'));
        $data_type = $this->request->input('data_type');

        // 校验 data_type
        if ($data_type !== null && !in_array($data_type, DashboardStatsService::VALID_DATA_TYPES, true)) {
            return $this->response->json([
                'code' => 400,
                'message' => "无效的 data_type 参数: {$data_type}，可选值: " . implode(', ', DashboardStatsService::VALID_DATA_TYPES),
                'data' => null,
            ])->withStatus(400);
        }

        // 校验日期格式
        if (!$this->isValidDate($from) || !$this->isValidDate($to)) {
            return $this->response->json([
                'code' => 400,
                'message' => '无效的日期格式，请使用 YYYY-MM-DD',
                'data' => null,
            ])->withStatus(400);
        }

        $scope_type = $this->request->getAttribute('scope_type', 'all');
        $scope_ids = $this->request->getAttribute('scope_ids', []);

        $data = $this->statsService->getBreakdown($dimension, $from, $to, $data_type, $scope_type, $scope_ids);

        return [
            'code' => 0,
            'message' => '获取成功',
            'data' => $data,
        ];
    }

    /**
     * 校验日期格式 YYYY-MM-DD
     */
    private function isValidDate(string $date): bool
    {
        $d = \DateTime::createFromFormat('Y-m-d', $date);
        return $d !== false && $d->format('Y-m-d') === $date;
    }
}
