<?php

namespace App\Services;

use App\Models\Tenants\TodayIssue;
use Carbon\Carbon;

/**
 * CEO 대시보드 오늘의 이슈 리스트 서비스
 *
 * today_issues 테이블에서 실시간 저장된 데이터를 조회
 */
class TodayIssueService extends Service
{
    /**
     * 오늘의 이슈 리스트 조회
     *
     * @param  int  $limit  조회할 최대 항목 수 (기본 30)
     * @param  string|null  $badge  뱃지 필터 (null이면 전체)
     * @param  string|null  $date  조회 날짜 (YYYY-MM-DD, null이면 오늘)
     */
    public function summary(int $limit = 30, ?string $badge = null, ?string $date = null): array
    {
        $tenantId = $this->tenantId();
        $userId = $this->apiUserId();

        // date 파라미터가 있으면 해당 날짜, 없으면 오늘
        $targetDate = $date ? Carbon::parse($date) : today();

        $query = TodayIssue::query()
            ->where('tenant_id', $tenantId)
            ->forUser($userId) // 본인 대상 또는 전체 브로드캐스트
            ->whereDate('created_at', $targetDate)
            ->orderByDesc('created_at');

        // 이전 이슈 조회 시에는 만료 필터 무시 (과거 데이터도 조회 가능)
        if (! $date) {
            $query->active(); // 오늘 이슈만 만료 필터 적용
        }

        // 뱃지 필터
        if ($badge !== null && $badge !== 'all') {
            $query->byBadge($badge);
        }

        // 전체 개수 (필터 적용 전)
        $totalQuery = TodayIssue::query()
            ->where('tenant_id', $tenantId)
            ->forUser($userId)
            ->whereDate('created_at', $targetDate);

        if (! $date) {
            $totalQuery->active();
        }

        $totalCount = $totalQuery->count();

        // 결과 조회
        $issues = $query->limit($limit)->get();

        $items = $issues->map(function (TodayIssue $issue) {
            // source_type 기반으로 badge 매핑 (DB 값보다 우선)
            $badge = TodayIssue::SOURCE_TO_BADGE[$issue->source_type] ?? $issue->badge ?? '기타';

            return [
                'id' => $issue->source_type.'_'.$issue->source_id,
                'badge' => $badge,
                'content' => $issue->content,
                'time' => $this->formatRelativeTime($issue->created_at),
                'date' => $issue->created_at?->toDateString(),
                'needsApproval' => $issue->needs_approval,
                'path' => $issue->path,
            ];
        })->toArray();

        return [
            'items' => $items,
            'total_count' => $totalCount,
        ];
    }

    /**
     * 읽지 않은 이슈 목록 조회 (헤더 알림용)
     *
     * @param  int  $limit  조회할 최대 항목 수 (기본 10)
     */
    public function getUnreadList(int $limit = 10): array
    {
        $tenantId = $this->tenantId();
        $userId = $this->apiUserId();

        $issues = TodayIssue::query()
            ->where('tenant_id', $tenantId)
            ->forUser($userId) // 본인 대상 또는 전체 브로드캐스트
            ->unread()
            ->active()
            ->orderByDesc('created_at')
            ->limit($limit)
            ->get();

        $totalCount = TodayIssue::query()
            ->where('tenant_id', $tenantId)
            ->forUser($userId)
            ->unread()
            ->active()
            ->count();

        $items = $issues->map(function (TodayIssue $issue) {
            // source_type 기반으로 badge 매핑 (DB 값보다 우선)
            $badge = TodayIssue::SOURCE_TO_BADGE[$issue->source_type] ?? $issue->badge ?? '기타';

            return [
                'id' => $issue->id,
                'badge' => $badge,
                'notification_type' => $issue->notification_type,
                'content' => $issue->content,
                'path' => $issue->path,
                'needs_approval' => $issue->needs_approval,
                'time' => $this->formatRelativeTime($issue->created_at),
                'created_at' => $issue->created_at?->toIso8601String(),
            ];
        })->toArray();

        return [
            'items' => $items,
            'total' => $totalCount,
        ];
    }

    /**
     * 읽지 않은 이슈 개수 조회 (헤더 알림 뱃지용)
     */
    public function getUnreadCount(): int
    {
        $tenantId = $this->tenantId();
        $userId = $this->apiUserId();

        return TodayIssue::query()
            ->where('tenant_id', $tenantId)
            ->forUser($userId) // 본인 대상 또는 전체 브로드캐스트
            ->unread()
            ->active()
            ->count();
    }

    /**
     * 이슈 확인 처리
     */
    public function markAsRead(int $issueId): bool
    {
        $tenantId = $this->tenantId();
        $userId = $this->apiUserId();

        $issue = TodayIssue::where('tenant_id', $tenantId)
            ->forUser($userId) // 본인 대상 또는 전체 브로드캐스트
            ->where('id', $issueId)
            ->first();

        if (! $issue) {
            return false;
        }

        return $issue->markAsRead($userId);
    }

    /**
     * 모든 이슈 읽음 처리
     */
    public function markAllAsRead(): int
    {
        $tenantId = $this->tenantId();
        $userId = $this->apiUserId();

        return TodayIssue::query()
            ->where('tenant_id', $tenantId)
            ->forUser($userId) // 본인 대상 또는 전체 브로드캐스트
            ->unread()
            ->active()
            ->update([
                'is_read' => true,
                'read_by' => $userId,
                'read_at' => now(),
            ]);
    }

    /**
     * 이슈 삭제 (확인 완료 처리)
     */
    public function dismiss(string $sourceType, int $sourceId): bool
    {
        $tenantId = $this->tenantId();

        return TodayIssue::removeBySource($tenantId, $sourceType, $sourceId);
    }

    /**
     * 뱃지별 개수 조회
     */
    public function countByBadge(): array
    {
        $tenantId = $this->tenantId();
        $userId = $this->apiUserId();

        $counts = TodayIssue::query()
            ->where('tenant_id', $tenantId)
            ->forUser($userId) // 본인 대상 또는 전체 브로드캐스트
            ->active()
            ->selectRaw('badge, COUNT(*) as count')
            ->groupBy('badge')
            ->pluck('count', 'badge')
            ->toArray();

        // 전체 개수 추가
        $counts['all'] = array_sum($counts);

        return $counts;
    }

    /**
     * 만료된 이슈 정리 (스케줄러에서 호출)
     */
    public function cleanupExpiredIssues(): int
    {
        return TodayIssue::where('expires_at', '<', now())->delete();
    }

    /**
     * 등록 시간 포맷팅
     * - 오늘: "14:30"
     * - 어제: "어제 14:30"
     * - 그 외: "1/22 14:30"
     */
    private function formatRelativeTime(?Carbon $datetime): string
    {
        if (! $datetime) {
            return '';
        }

        $now = Carbon::now();
        $time = $datetime->format('H:i');

        // 오늘
        if ($datetime->isToday()) {
            return $time;
        }

        // 어제
        if ($datetime->isYesterday()) {
            return __('message.today_issue.time_yesterday').' '.$time;
        }

        // 그 외
        return $datetime->format('n/j').' '.$time;
    }
}
