<?php
namespace App\Controllers;

use App\Services\ActivityService;
use App\Services\VirtualStageService;
use App\Services\DidarApiService;
use App\Services\AuthService;
use App\Services\AuditService;
use App\Repositories\PersonRepository;
use App\Utils\Sanitizer;

class ActivityController extends ApiController
{
    private $activityService;
    private $virtualStageService;
    private $didarApi;
    private $authService;
    private $personRepo;
    private $auditService;

    public function __construct(
        ActivityService $activityService,
        VirtualStageService $virtualStageService,
        DidarApiService $didarApi,
        AuthService $authService,
        PersonRepository $personRepo,
        ?AuditService $auditService = null
    ) {
        $this->activityService = $activityService;
        $this->virtualStageService = $virtualStageService;
        $this->didarApi = $didarApi;
        $this->authService = $authService;
        $this->personRepo = $personRepo;
        $this->auditService = $auditService;
    }

    private function canRbac(string $capabilityKey): bool
    {
        global $app;
        if (isset($app->services->rbac) && $app->services->rbac) {
            return (bool)$app->services->rbac->can($capabilityKey);
        }
        return false;
    }

    private function assertDealWritableForActivity(string $dealId): void
    {
        $dealId = trim($dealId);
        if ($dealId === '') {
            return;
        }

        global $app;
        if (!isset($app->repositories->deal) || !$app->repositories->deal) {
            return;
        }

        $deal = $app->repositories->deal->findByDidarId($dealId);
        if ($deal && (int)($deal->is_legacy_didar ?? 0) === 1) {
            $this->errorResponse('معاملات گذشته دیدار فقط قابل مشاهده هستند و امکان ثبت فعالیت ندارند', 423);
        }
    }

    public function save()
    {
        // Log incoming data for debugging
        \App\Utils\Logger::logInfo("Activity save request", ['post_data' => $_POST]);
        
        $contactIdInput = Sanitizer::sanitize($_POST['contact_id'] ?? '');
        
        // Prefer strict Didar lookup to avoid local numeric ID collisions
        $person = $this->personRepo->findByDidarId($contactIdInput);
        if (!$person) {
            $person = $this->personRepo->findByIdOrDidarId($contactIdInput);
        }

        if (!$person) {
            $this->errorResponse('لید با این شناسه یافت نشد');
        }

        // Standardize to the real Didar GUID for ALL internal processing
        $standardContactId = $person->didar_contact_id;
        // --- END STRICT LOOKUP ---

        $data = [
            'didar_activity_id' => Sanitizer::sanitize($_POST['activity_id'] ?? ''),
            'contact_didar_id' => $standardContactId,
            'deal_didar_id' => Sanitizer::sanitize($_POST['deal_id'] ?? ''),
            'activity_type_id' => Sanitizer::sanitize($_POST['activity_type_id'] ?? ''),
            'activity_type_title' => Sanitizer::sanitize($_POST['activity_type_title'] ?? ''),
            'note' => Sanitizer::sanitize($_POST['note'] ?? ''),
            'result_note' => Sanitizer::sanitize($_POST['result_note'] ?? ''),
            'activity_duration' => max(0, (int)($_POST['activity_duration'] ?? 0)),
            'call_type' => Sanitizer::sanitize($_POST['call_type'] ?? ''),
            'direction' => Sanitizer::sanitize($_POST['direction'] ?? 'outgoing'),
            'is_done' => (isset($_POST['is_done']) && $_POST['is_done'] == '1') ? 1 : 0,
            'due_date' => Sanitizer::sanitize($_POST['due_date'] ?? ''),
            'reminder_enabled' => isset($_POST['reminder_enabled']) ? $_POST['reminder_enabled'] : '0',
            'reminder_offset_minutes' => isset($_POST['reminder_offset_minutes']) ? (int)$_POST['reminder_offset_minutes'] : 1440,
            'register_date' => date('Y-m-d H:i:s'),
            'last_sync' => date('Y-m-d H:i:s'),
            'requested_services' => $_POST['requested_services'] ?? '',
            'financial_level' => isset($_POST['financial_level']) ? Sanitizer::sanitize($_POST['financial_level']) : null,
            'asset_estimation' => isset($_POST['asset_estimation']) ? Sanitizer::sanitize($_POST['asset_estimation']) : null,
            'income_estimation' => isset($_POST['income_estimation']) ? Sanitizer::sanitize($_POST['income_estimation']) : null,
            'failure_reason' => isset($_POST['failure_reason']) ? Sanitizer::sanitize($_POST['failure_reason']) : null,
            'failure_other_description' => isset($_POST['failure_other_description']) ? Sanitizer::sanitize($_POST['failure_other_description']) : null,
            'city' => isset($_POST['city']) ? Sanitizer::sanitize($_POST['city']) : null,
            'job_title' => isset($_POST['job_title']) ? Sanitizer::sanitize($_POST['job_title']) : null,
            'job_description' => isset($_POST['job_description']) ? Sanitizer::sanitize($_POST['job_description']) : null,
            'acquaintance_duration' => isset($_POST['acquaintance_duration']) ? Sanitizer::sanitize($_POST['acquaintance_duration']) : null,
            'extra_info' => isset($_POST['extra_info']) ? Sanitizer::sanitize($_POST['extra_info']) : null
        ];

        $this->assertDealWritableForActivity((string)$data['deal_didar_id']);
        
        if (empty($data['contact_didar_id']) || empty($data['activity_type_id'])) {
            \App\Utils\Logger::logError("Activity save validation failed", null, ['data' => $data]);
            $this->errorResponse('شناسه شخص و نوع فعالیت الزامی است');
        }
        if ($data['activity_duration'] <= 0) {
            $this->errorResponse('مدت زمان فعالیت الزامی است');
        }
        if (!in_array($data['call_type'], ['voip', 'phone', 'sms'], true)) {
            $this->errorResponse('نوع مکالمه الزامی است');
        }
        
        // Check if activity is scheduled for future
        $isScheduled = isset($_POST['is_scheduled']) && $_POST['is_scheduled'] == '1';
        
        // Deal pipeline stage (optional)
        $pipelineStage = Sanitizer::sanitize($_POST['pipeline_stage'] ?? '');
        
        // Save activity (will handle Didar API call and virtual stage update)
        try {
            $activityId = $this->activityService->saveActivity($data, null, null, $pipelineStage);
            $this->successResponse(['activity_id' => $activityId], 'فعالیت با موفقیت ثبت شد');
        } catch (\Exception $e) {
            \App\Utils\Logger::logError("Error saving activity", $e, ['data' => $data]);
            $this->errorResponse('خطا در ثبت فعالیت: ' . $e->getMessage());
        }
    }

    public function update()
    {
        $activityId = Sanitizer::sanitize($_POST['activity_id'] ?? '');
        
        if (empty($activityId)) {
            $this->errorResponse('شناسه فعالیت الزامی است');
        }
        
        $data = [
            'didar_activity_id' => $activityId,
            'activity_type_id' => Sanitizer::sanitize($_POST['activity_type_id'] ?? ''),
            'due_date' => Sanitizer::sanitize($_POST['due_date'] ?? ''),
            'reminder_enabled' => isset($_POST['reminder_enabled']) ? $_POST['reminder_enabled'] : '0',
            'reminder_offset_minutes' => isset($_POST['reminder_offset_minutes']) ? (int)$_POST['reminder_offset_minutes'] : 1440,
        ];
        
        if (empty($data['activity_type_id'])) {
            $this->errorResponse('نوع فعالیت الزامی است');
        }
        
        try {
            $this->activityService->updateScheduledActivity($activityId, $data);
            $this->successResponse([], 'فعالیت با موفقیت به‌روزرسانی شد');
        } catch (\Exception $e) {
            \App\Utils\Logger::logError("Error updating activity", $e, ['data' => $data]);
            $this->errorResponse('خطا در به‌روزرسانی فعالیت: ' . $e->getMessage());
        }
    }

    public function delete()
    {
        if (!$this->canRbac('activities.delete') && !$this->hasDelegatedCapability('activities.admin.delete')) {
            $this->errorResponse('فقط مدیر سیستم می‌تواند فعالیت‌ها را حذف کند');
        }
        
        $activityId = Sanitizer::sanitize($_POST['activity_id'] ?? '');
        
        if (empty($activityId)) {
            $this->errorResponse('شناسه فعالیت الزامی است');
        }

        $existingActivity = $this->activityService->getActivityByDidarId($activityId);
        if (!$existingActivity && is_numeric($activityId)) {
            $existingActivity = $this->activityService->getActivityById((int) $activityId);
        }
        if ($this->auditService) {
            $this->auditService->log('delete', 'activity', $activityId, [
                'activity' => $existingActivity ? $existingActivity->toArray() : null,
            ]);
        }
        
        $this->activityService->deleteActivity($activityId);
        $this->successResponse([], 'فعالیت با موفقیت حذف شد');
    }

    public function getActivityTypes()
    {
        // Prefer fetching real ActivityTypeIds from Didar so saving activities works reliably.
        $fallbackTypes = [
            [
                'Id' => '2a335dc1-4834-484b-b6dc-9ddd97eef67e', // تماس ورودی
                'Title' => 'تماس ورودی',
                'Direction' => 'incoming',
                'Category' => 'call',
                'IsDisabled' => false,
                'IsConnection' => true
            ],
            [
                'Id' => '790079e8-74ac-4760-9527-097627d3e7ec', // تماس خروجی
                'Title' => 'تماس خروجی',
                'Direction' => 'outgoing',
                'Category' => 'call',
                'IsDisabled' => false,
                'IsConnection' => true
            ],
            [
                'Id' => '3b446dc2-5945-595c-c7ed-0eee08ff78fd', // چت ورودی
                'Title' => 'چت ورودی',
                'Direction' => 'incoming',
                'Category' => 'chat',
                'IsDisabled' => false,
                'IsConnection' => false
            ],
            [
                'Id' => '4c557ed3-6a56-606d-d8fe-1fff19gg89ge', // چت خروجی
                'Title' => 'چت خروجی',
                'Direction' => 'outgoing',
                'Category' => 'chat',
                'IsDisabled' => false,
                'IsConnection' => false
            ],
            [
                'Id' => 'b9f2f0c6-7f4a-4f49-9c71-9a0d4d2d1f16', // مراجعه حضوری (fallback)
                'Title' => 'مراجعه حضوری',
                'Direction' => 'outgoing',
                'Category' => 'meeting',
                'IsDisabled' => false,
                'IsConnection' => true
            ],
        ];

        try {
            $res = $this->didarApi->call('/activity/GetActivityType', 'POST', []);
            $allTypes = isset($res['Response']) && is_array($res['Response']) ? $res['Response'] : [];

            $picked = [];
            foreach ($allTypes as $type) {
                $title = (string)($type['Title'] ?? '');
                $isDisabled = (bool)($type['IsDisabled'] ?? false);
                if ($isDisabled) continue;

                if (stripos($title, 'تماس ورودی') !== false && !isset($picked['تماس ورودی'])) {
                    $picked['تماس ورودی'] = $type;
                    $picked['تماس ورودی']['Title'] = 'تماس ورودی';
                    $picked['تماس ورودی']['Direction'] = 'incoming';
                    $picked['تماس ورودی']['Category'] = 'call';
                } elseif (stripos($title, 'تماس خروجی') !== false && !isset($picked['تماس خروجی'])) {
                    $picked['تماس خروجی'] = $type;
                    $picked['تماس خروجی']['Title'] = 'تماس خروجی';
                    $picked['تماس خروجی']['Direction'] = 'outgoing';
                    $picked['تماس خروجی']['Category'] = 'call';
                } elseif (stripos($title, 'چت') !== false) {
                    $direction = (stripos($title, 'ورودی') !== false) ? 'incoming' : 'outgoing';
                    $key = $direction === 'incoming' ? 'چت ورودی' : 'چت خروجی';
                    if (!isset($picked[$key])) {
                        $picked[$key] = $type;
                        $picked[$key]['Title'] = $key;
                        $picked[$key]['Direction'] = $direction;
                        $picked[$key]['Category'] = 'chat';
                    }
                } elseif (
                    (stripos($title, 'مراجعه حضوری') !== false || stripos($title, 'حضوری') !== false) &&
                    !isset($picked['مراجعه حضوری'])
                ) {
                    $picked['مراجعه حضوری'] = $type;
                    $picked['مراجعه حضوری']['Title'] = 'مراجعه حضوری';
                    $picked['مراجعه حضوری']['Direction'] = 'outgoing';
                    $picked['مراجعه حضوری']['Category'] = 'meeting';
                }
            }

            // Ensure all required titles exist (fallback if missing from Didar)
            $final = [];
            foreach ($fallbackTypes as $fb) {
                $key = $fb['Title'];
                $final[] = $picked[$key] ?? $fb;
            }

            $this->successResponse(['types' => $final]);
            return;
        } catch (\Exception $e) {
            \App\Utils\Logger::logWarning('getActivityTypes fallback used', ['error' => $e->getMessage()]);
            $this->successResponse(['types' => $fallbackTypes]);
            return;
        }
    }

    /**
     * Get activity details by ID
     */
    public function getActivityDetails()
    {
        $activityId = Sanitizer::sanitize($_POST['activity_id'] ?? '');

        if (empty($activityId)) {
            $this->errorResponse('شناسه فعالیت الزامی است');
        }

        // Get from local database first via an indexed point lookup on the unique
        // didar_activity_id (previously this pulled up to 1000 full rows incl. raw_json
        // LONGTEXT and linear-scanned them in PHP).
        $activity = $this->activityService->getActivityByDidarId($activityId);

        // Local-only activities (created while Didar sync is disabled) have no
        // didar_activity_id, so the frontend sends the local primary key instead.
        // Fall back to a point lookup by id before reaching out to Didar.
        if (!$activity && is_numeric($activityId)) {
            $activity = $this->activityService->getActivityById((int) $activityId);
        }

        // If not found locally, get from Didar
        if (!$activity) {
            $res = $this->didarApi->call('/activity/search', 'POST', [
                'ActivityId' => $activityId,
                'FromDate' => '1901-01-01T00:00:00.000Z',
                'ToDate' => '9999-12-01T00:00:00.000Z',
                'IsDone' => -1,
                'From' => 0,
                'Limit' => 1,
            ]);

            if (isset($res['error']) || !isset($res['Response']['List']) || empty($res['Response']['List'])) {
                $this->errorResponse('فعالیت یافت نشد');
            }

            $activity = $res['Response']['List'][0];
            
            // Ensure due_date and is_scheduled are included
            if (!isset($activity['due_date']) && isset($activity['DueDate'])) {
                $activity['due_date'] = $activity['DueDate'];
            }
            if (!isset($activity['is_scheduled'])) {
                // Determine if scheduled based on due date and is_done
                $hasDueDate = !empty($activity['DueDate']);
                $isDone = $activity['IsDone'] ?? false;
                $activity['is_scheduled'] = (!$isDone && $hasDueDate) ? 1 : 0;
            }
        } else {
            // Convert local activity to Didar format
            $activity = [
                'Id' => $activity->didar_activity_id ?: (string) $activity->id,
                'ActivityTypeId' => $activity->activity_type_id,
                'ActivityTypeTitle' => $activity->activity_type_title,
                'Title' => $activity->title,
                'Note' => $activity->note,
                'ResultNote' => $activity->result_note,
                'IsDone' => $activity->is_done,
                'DueDate' => $activity->due_date,
                'due_date' => $activity->due_date, // Also include lowercase version
                'RegisterDate' => $activity->register_date,
                'register_date' => $activity->register_date, // Also include lowercase version
                'DoneDate' => $activity->done_date,
                'is_scheduled' => $activity->is_scheduled ?? 0,
                'reminder_enabled' => $activity->reminder_enabled ?? 0,
                'last_update_time' => $activity->last_update_time ?? null,
                'ContactIds' => [$activity->contact_didar_id],
                'Notifies' => []
            ];
        }

        $this->successResponse(['activity' => $activity]);
    }

    /**
     * Get activities for a specific deal from Didar (remote source).
     * Mirrors the legacy get_deal_activities endpoint.
     */
    public function getDealActivities()
    {
        $dealId = Sanitizer::sanitize($_POST['deal_id'] ?? '');

        if (empty($dealId)) {
            $this->errorResponse('شناسه معامله الزامی است');
        }

        $activities = $this->activityService->getActivitiesByDeal($dealId, 200);
        $this->successResponse(['activities' => $activities]);
    }

    /**
     * Check in local database whether a deal already has at least one activity.
     * No Didar API call is performed.
     */
    public function hasDealActivity()
    {
        $dealId = Sanitizer::sanitize($_POST['deal_id'] ?? '');
        if (empty($dealId)) {
            $this->errorResponse('شناسه معامله الزامی است');
        }

        $hasActivity = $this->activityService->hasActivityForDeal($dealId);
        $this->successResponse(['has_activity' => $hasActivity]);
    }

    /**
     * Get local activities for a contact (no Didar API).
     */
    public function getContactActivitiesLocal()
    {
        $contactId = Sanitizer::sanitize($_POST['contact_id'] ?? '');
        if (empty($contactId)) {
            $this->errorResponse('شناسه لید الزامی است');
        }
        $activities = $this->activityService->getActivitiesByContact($contactId, 200);
        $this->successResponse(['activities' => $activities]);
    }
}

