<?php

namespace App\Sms\Controller;

use App\Auth\Entity\User;
use App\Shared\Constant\ErrorCodes;
use App\Shared\Controller\BaseController;
use App\Sms\Entity\SmsTemplate;
use App\Sms\Repository\SmsTemplateRepository;
use App\Sms\Service\SmsService;
use OpenApi\Attributes as OA;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\CurrentUser;
use Symfony\Component\Security\Http\Attribute\IsGranted;

#[OA\Tag(name: 'SMS')]
#[IsGranted('IS_AUTHENTICATED_FULLY')]
class SmsController extends BaseController
{
    public function __construct(
        private readonly SmsTemplateRepository $templateRepo,
        private readonly SmsService            $smsService,
    ) {}

    // ── Send SMS directly ─────────────────────────────────────────────────────

    #[OA\Post(
        path: '/api/v1/sms/send',
        summary: 'Send an SMS message directly (ROLE_ADMIN)',
        security: [['bearerAuth' => []]],
        requestBody: new OA\RequestBody(
            required: true,
            content: new OA\JsonContent(
                required: ['mobile', 'message'],
                properties: [
                    new OA\Property(property: 'mobile', type: 'string'),
                    new OA\Property(property: 'message', type: 'string'),
                    new OA\Property(property: 'provider', type: 'string', default: 'kavenegar'),
                ]
            )
        ),
        responses: [
            new OA\Response(
                response: 200,
                description: 'SMS queued for delivery',
                content: new OA\JsonContent(
                    properties: [
                        new OA\Property(property: 'success', type: 'boolean', example: true),
                        new OA\Property(property: 'data', properties: [
                            new OA\Property(property: 'message', type: 'string'),
                        ], type: 'object'),
                    ]
                )
            ),
            new OA\Response(response: 401, description: 'Unauthorized'),
            new OA\Response(response: 403, description: 'Forbidden – ROLE_ADMIN required'),
            new OA\Response(response: 422, description: 'Validation error'),
        ]
    )]
    #[IsGranted('ROLE_ADMIN')]
    #[Route('/api/v1/sms/send', methods: ['POST'])]
    public function send(Request $request): JsonResponse
    {
        // سیاست lookup-only: ارسال متن آزاد با sms/send.json مجاز نیست (در ایران فیلتر می‌شود).
        // برای ارسال دستی از تمپلیت تأییدشده استفاده کنید: POST /api/v1/sms/send-via-template
        return $this->error(ErrorCodes::ERR_VALIDATION_001, 'ارسال متن آزاد مجاز نیست؛ از تمپلیت تأییدشده (VerifyLookup) استفاده کنید', 422);
    }

    // ── Templates ─────────────────────────────────────────────────────────────

    #[OA\Post(
        path: '/api/v1/sms/template',
        summary: 'Create a new SMS template (ROLE_ADMIN)',
        security: [['bearerAuth' => []]],
        requestBody: new OA\RequestBody(
            required: true,
            content: new OA\JsonContent(
                required: ['name', 'body'],
                properties: [
                    new OA\Property(property: 'name', type: 'string'),
                    new OA\Property(property: 'body', type: 'string'),
                    new OA\Property(property: 'variables', type: 'array', items: new OA\Items(type: 'string')),
                ]
            )
        ),
        responses: [
            new OA\Response(
                response: 201,
                description: 'Template created',
                content: new OA\JsonContent(
                    properties: [
                        new OA\Property(property: 'success', type: 'boolean', example: true),
                        new OA\Property(property: 'data', type: 'object'),
                    ]
                )
            ),
            new OA\Response(response: 401, description: 'Unauthorized'),
            new OA\Response(response: 403, description: 'Forbidden – ROLE_ADMIN required'),
            new OA\Response(response: 422, description: 'Validation error'),
        ]
    )]
    #[IsGranted('ROLE_ADMIN')]
    #[Route('/api/v1/sms/template', methods: ['POST'])]
    public function createTemplate(Request $request): JsonResponse
    {
        $data      = json_decode($request->getContent(), true) ?? [];
        $name      = trim($data['name'] ?? '');
        $body      = trim($data['body'] ?? '');
        $variables = $data['variables'] ?? [];

        if (empty($name) || empty($body)) {
            return $this->error(ErrorCodes::ERR_VALIDATION_002, 'name و body الزامی است', 422);
        }

        $template = new SmsTemplate($name, $body, $variables);
        $this->templateRepo->save($template);

        return $this->success(['data' => $template->toArray()], 201);
    }

    #[OA\Get(
        path: '/api/v1/sms/template/{uuid}',
        summary: 'Get an SMS template by UUID',
        security: [['bearerAuth' => []]],
        parameters: [
            new OA\Parameter(name: 'uuid', in: 'path', required: true, schema: new OA\Schema(type: 'string')),
        ],
        responses: [
            new OA\Response(
                response: 200,
                description: 'Template details',
                content: new OA\JsonContent(
                    properties: [
                        new OA\Property(property: 'success', type: 'boolean', example: true),
                        new OA\Property(property: 'data', type: 'object'),
                    ]
                )
            ),
            new OA\Response(response: 401, description: 'Unauthorized'),
            new OA\Response(response: 404, description: 'Not found'),
        ]
    )]
    #[Route('/api/v1/sms/template/{uuid}', methods: ['GET'])]
    public function getTemplate(string $uuid): JsonResponse
    {
        $template = $this->templateRepo->findByUuid($uuid);
        if ($template === null) {
            return $this->error(ErrorCodes::ERR_NOT_FOUND_001, 'تمپلیت یافت نشد', 404);
        }
        return $this->success(['data' => $template->toArray()]);
    }

    #[OA\Patch(
        path: '/api/v1/sms/template/{uuid}',
        summary: 'Update an SMS template (ROLE_ADMIN, only non-approved templates)',
        security: [['bearerAuth' => []]],
        requestBody: new OA\RequestBody(
            required: false,
            content: new OA\JsonContent(
                properties: [
                    new OA\Property(property: 'name', type: 'string'),
                    new OA\Property(property: 'body', type: 'string'),
                    new OA\Property(property: 'variables', type: 'array', items: new OA\Items(type: 'string')),
                ]
            )
        ),
        parameters: [
            new OA\Parameter(name: 'uuid', in: 'path', required: true, schema: new OA\Schema(type: 'string')),
        ],
        responses: [
            new OA\Response(
                response: 200,
                description: 'Template updated',
                content: new OA\JsonContent(
                    properties: [
                        new OA\Property(property: 'success', type: 'boolean', example: true),
                        new OA\Property(property: 'data', type: 'object'),
                    ]
                )
            ),
            new OA\Response(response: 401, description: 'Unauthorized'),
            new OA\Response(response: 403, description: 'Forbidden – ROLE_ADMIN required'),
            new OA\Response(response: 404, description: 'Not found'),
            new OA\Response(response: 422, description: 'Template is already approved and cannot be edited'),
        ]
    )]
    #[IsGranted('ROLE_ADMIN')]
    #[Route('/api/v1/sms/template/{uuid}', methods: ['PATCH'])]
    public function updateTemplate(string $uuid, Request $request): JsonResponse
    {
        $template = $this->templateRepo->findByUuid($uuid);
        if ($template === null) {
            return $this->error(ErrorCodes::ERR_NOT_FOUND_001, 'تمپلیت یافت نشد', 404);
        }

        $data = json_decode($request->getContent(), true) ?? [];

        // ویرایش محتوای یک قالبِ تأییدشده، آن را به پیش‌نویس برمی‌گرداند تا متن جدید
        // دوباره تأیید/ارسال شود (متن قبلی با سرویس‌دهنده هماهنگ بوده).
        $contentChanged = array_key_exists('name', $data) || array_key_exists('body', $data) || array_key_exists('variables', $data);
        if ($template->getStatus() === SmsTemplate::STATUS_APPROVED && $contentChanged) {
            $template->revertToDraft();
        }

        if (array_key_exists('name', $data))      $template->setName($data['name']);
        if (array_key_exists('body', $data))      $template->setBody($data['body']);
        if (array_key_exists('variables', $data)) $template->setVariables($data['variables']);

        $this->templateRepo->save($template);

        return $this->success(['data' => $template->toArray()]);
    }

    #[OA\Post(
        path: '/api/v1/sms/template/{uuid}/submit',
        summary: 'Submit an SMS template for review (ROLE_ADMIN)',
        security: [['bearerAuth' => []]],
        parameters: [
            new OA\Parameter(name: 'uuid', in: 'path', required: true, schema: new OA\Schema(type: 'string')),
        ],
        responses: [
            new OA\Response(
                response: 200,
                description: 'Template submitted for review',
                content: new OA\JsonContent(
                    properties: [
                        new OA\Property(property: 'success', type: 'boolean', example: true),
                        new OA\Property(property: 'data', type: 'object'),
                    ]
                )
            ),
            new OA\Response(response: 401, description: 'Unauthorized'),
            new OA\Response(response: 403, description: 'Forbidden – ROLE_ADMIN required'),
            new OA\Response(response: 404, description: 'Not found'),
        ]
    )]
    #[IsGranted('ROLE_ADMIN')]
    #[Route('/api/v1/sms/template/{uuid}/submit', methods: ['POST'])]
    public function submitTemplate(string $uuid): JsonResponse
    {
        $template = $this->templateRepo->findByUuid($uuid);
        if ($template === null) {
            return $this->error(ErrorCodes::ERR_NOT_FOUND_001, 'تمپلیت یافت نشد', 404);
        }

        $template->submitForReview();
        $this->templateRepo->save($template);

        return $this->success(['data' => $template->toArray()]);
    }

    #[OA\Delete(
        path: '/api/v1/sms/template/{uuid}',
        summary: 'Delete an SMS template (ROLE_ADMIN)',
        security: [['bearerAuth' => []]],
        parameters: [
            new OA\Parameter(name: 'uuid', in: 'path', required: true, schema: new OA\Schema(type: 'string')),
        ],
        responses: [
            new OA\Response(
                response: 200,
                description: 'Template deleted',
                content: new OA\JsonContent(
                    properties: [
                        new OA\Property(property: 'success', type: 'boolean', example: true),
                        new OA\Property(property: 'data', properties: [
                            new OA\Property(property: 'message', type: 'string'),
                        ], type: 'object'),
                    ]
                )
            ),
            new OA\Response(response: 401, description: 'Unauthorized'),
            new OA\Response(response: 403, description: 'Forbidden – ROLE_ADMIN required'),
            new OA\Response(response: 404, description: 'Not found'),
        ]
    )]
    #[IsGranted('ROLE_ADMIN')]
    #[Route('/api/v1/sms/template/{uuid}', methods: ['DELETE'])]
    public function deleteTemplate(string $uuid): JsonResponse
    {
        $template = $this->templateRepo->findByUuid($uuid);
        if ($template === null) {
            return $this->error(ErrorCodes::ERR_NOT_FOUND_001, 'تمپلیت یافت نشد', 404);
        }
        $this->templateRepo->remove($template);
        return $this->success(['message' => 'تمپلیت حذف شد']);
    }

    // ── Admin moderation ──────────────────────────────────────────────────────

    #[OA\Get(
        path: '/api/v1/admin/sms/templates',
        summary: 'List all SMS templates (ROLE_ADMIN)',
        security: [['bearerAuth' => []]],
        responses: [
            new OA\Response(
                response: 200,
                description: 'List of all SMS templates',
                content: new OA\JsonContent(
                    properties: [
                        new OA\Property(property: 'success', type: 'boolean', example: true),
                        new OA\Property(property: 'data', type: 'array', items: new OA\Items(type: 'object')),
                    ]
                )
            ),
            new OA\Response(response: 401, description: 'Unauthorized'),
            new OA\Response(response: 403, description: 'Forbidden – ROLE_ADMIN required'),
        ]
    )]
    #[IsGranted('ROLE_ADMIN')]
    #[Route('/api/v1/admin/sms/templates', methods: ['GET'])]
    public function listTemplates(): JsonResponse
    {
        $templates = array_map(fn(SmsTemplate $t) => $t->toArray(), $this->templateRepo->findAll());
        return $this->success(['data' => $templates]);
    }

    #[OA\Post(
        path: '/api/v1/admin/sms/template/{uuid}/approve',
        summary: 'Approve an SMS template (ROLE_ADMIN)',
        security: [['bearerAuth' => []]],
        requestBody: new OA\RequestBody(
            required: false,
            content: new OA\JsonContent(
                properties: [
                    new OA\Property(property: 'note', type: 'string', nullable: true),
                    new OA\Property(property: 'provider_code', type: 'string', nullable: true),
                ]
            )
        ),
        parameters: [
            new OA\Parameter(name: 'uuid', in: 'path', required: true, schema: new OA\Schema(type: 'string')),
        ],
        responses: [
            new OA\Response(
                response: 200,
                description: 'Template approved',
                content: new OA\JsonContent(
                    properties: [
                        new OA\Property(property: 'success', type: 'boolean', example: true),
                        new OA\Property(property: 'data', type: 'object'),
                    ]
                )
            ),
            new OA\Response(response: 401, description: 'Unauthorized'),
            new OA\Response(response: 403, description: 'Forbidden – ROLE_ADMIN required'),
            new OA\Response(response: 404, description: 'Not found'),
        ]
    )]
    #[IsGranted('ROLE_ADMIN')]
    #[Route('/api/v1/admin/sms/template/{uuid}/approve', methods: ['POST'])]
    public function approveTemplate(string $uuid, Request $request): JsonResponse
    {
        $template = $this->templateRepo->findByUuid($uuid);
        if ($template === null) {
            return $this->error(ErrorCodes::ERR_NOT_FOUND_001, 'تمپلیت یافت نشد', 404);
        }

        $data = json_decode($request->getContent(), true) ?? [];
        $template->approve($data['note'] ?? null);
        if (!empty($data['provider_code'])) $template->setProviderCode($data['provider_code']);
        $this->templateRepo->save($template);

        return $this->success(['data' => $template->toArray()]);
    }

    #[OA\Post(
        path: '/api/v1/admin/sms/template/{uuid}/reject',
        summary: 'Reject an SMS template (ROLE_ADMIN)',
        security: [['bearerAuth' => []]],
        requestBody: new OA\RequestBody(
            required: true,
            content: new OA\JsonContent(
                required: ['note'],
                properties: [
                    new OA\Property(property: 'note', type: 'string', description: 'Rejection reason (required)'),
                ]
            )
        ),
        parameters: [
            new OA\Parameter(name: 'uuid', in: 'path', required: true, schema: new OA\Schema(type: 'string')),
        ],
        responses: [
            new OA\Response(
                response: 200,
                description: 'Template rejected',
                content: new OA\JsonContent(
                    properties: [
                        new OA\Property(property: 'success', type: 'boolean', example: true),
                        new OA\Property(property: 'data', type: 'object'),
                    ]
                )
            ),
            new OA\Response(response: 401, description: 'Unauthorized'),
            new OA\Response(response: 403, description: 'Forbidden – ROLE_ADMIN required'),
            new OA\Response(response: 404, description: 'Not found'),
            new OA\Response(response: 422, description: 'Rejection note is required'),
        ]
    )]
    #[IsGranted('ROLE_ADMIN')]
    #[Route('/api/v1/admin/sms/template/{uuid}/reject', methods: ['POST'])]
    public function rejectTemplate(string $uuid, Request $request): JsonResponse
    {
        $template = $this->templateRepo->findByUuid($uuid);
        if ($template === null) {
            return $this->error(ErrorCodes::ERR_NOT_FOUND_001, 'تمپلیت یافت نشد', 404);
        }

        $data = json_decode($request->getContent(), true) ?? [];
        $note = trim($data['note'] ?? '');
        if (empty($note)) {
            return $this->error(ErrorCodes::ERR_VALIDATION_002, 'دلیل رد الزامی است', 422);
        }
        $template->reject($note);
        $this->templateRepo->save($template);

        return $this->success(['data' => $template->toArray()]);
    }

    // ── Send via template ─────────────────────────────────────────────────────

    #[OA\Post(
        path: '/api/v1/sms/send-template',
        summary: 'Send an SMS using an approved template (ROLE_ADMIN)',
        security: [['bearerAuth' => []]],
        requestBody: new OA\RequestBody(
            required: true,
            content: new OA\JsonContent(
                required: ['mobile', 'template_uuid'],
                properties: [
                    new OA\Property(property: 'mobile', type: 'string'),
                    new OA\Property(property: 'template_uuid', type: 'string'),
                    new OA\Property(property: 'vars', type: 'object', description: 'Key-value map of template variables'),
                    new OA\Property(property: 'provider', type: 'string', default: 'kavenegar'),
                ]
            )
        ),
        responses: [
            new OA\Response(
                response: 200,
                description: 'SMS queued via template',
                content: new OA\JsonContent(
                    properties: [
                        new OA\Property(property: 'success', type: 'boolean', example: true),
                        new OA\Property(property: 'data', properties: [
                            new OA\Property(property: 'message', type: 'string'),
                        ], type: 'object'),
                    ]
                )
            ),
            new OA\Response(response: 401, description: 'Unauthorized'),
            new OA\Response(response: 403, description: 'Forbidden – ROLE_ADMIN required'),
            new OA\Response(response: 404, description: 'Template not found'),
            new OA\Response(response: 422, description: 'Template not yet approved'),
        ]
    )]
    #[IsGranted('ROLE_ADMIN')]
    #[Route('/api/v1/sms/send-template', methods: ['POST'])]
    public function sendViaTemplate(Request $request): JsonResponse
    {
        $data         = json_decode($request->getContent(), true) ?? [];
        $mobile       = trim($data['mobile'] ?? '');
        $templateUuid = trim($data['template_uuid'] ?? '');
        $vars         = $data['vars'] ?? [];
        $provider     = $data['provider'] ?? 'kavenegar';

        $template = $this->templateRepo->findByUuid($templateUuid);
        if ($template === null) {
            return $this->error(ErrorCodes::ERR_NOT_FOUND_001, 'تمپلیت یافت نشد', 404);
        }

        if ($template->getStatus() !== SmsTemplate::STATUS_APPROVED) {
            return $this->error(ErrorCodes::ERR_VALIDATION_001, 'تمپلیت هنوز تأیید نشده است', 422);
        }

        // سیاست lookup-only: بدون کد VerifyLookup کاوه‌نگار قابل ارسال نیست.
        if (!$template->getProviderCode()) {
            return $this->error(ErrorCodes::ERR_VALIDATION_001, 'این تمپلیت کد VerifyLookup کاوه‌نگار ندارد و قابل ارسال نیست', 422);
        }

        $message = $template->renderBody($vars);
        $this->smsService->dispatchAsync(
            $mobile, $message, $provider, $template->getUuid(),
            $vars, $template->getProviderCode(), \App\Sms\Entity\SmsLog::TAG_USER_TEMPLATE
        );

        return $this->success(['message' => 'پیامک در صف ارسال قرار گرفت']);
    }
}
