<?php

namespace App\Http\Controllers;

use App\Models\SmsLog;
use App\Models\SmsTemplate;
use App\Models\SmsGateway;
use App\Models\SmsSchedule;
use App\Models\Student;
use App\Models\Teacher;
use App\Models\Fee;
use App\Models\Result;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use Illuminate\Support\Facades\DB;

class SmsController extends Controller
{
    /**
     * Display SMS dashboard
     */
    public function index()
    {
        $stats = [
            'total_sent' => SmsLog::whereDate('created_at', today())->count(),
            'total_cost' => SmsLog::whereDate('created_at', today())->sum('cost'),
            'success_rate' => $this->calculateSuccessRate(),
            'balance' => $this->getBalance()
        ];

        $recentSms = SmsLog::with('template', 'sender')
                          ->orderBy('created_at', 'desc')
                          ->limit(10)
                          ->get();

        $templates = SmsTemplate::where('is_active', true)->get();
        $gateways = SmsGateway::where('is_active', true)->get();

        return view('sms.index', compact('stats', 'recentSms', 'templates', 'gateways'));
    }

    /**
     * Send single SMS
     */
    public function sendSingle(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'phone_number' => 'required|string|max:20',
            'message' => 'required|string|max:160',
            'template_id' => 'nullable|exists:sms_templates,id',
            'purpose' => 'nullable|string'
        ]);

        if ($validator->fails()) {
            return response()->json(['errors' => $validator->errors()], 422);
        }

        try {
            $gateway = SmsGateway::getDefault();
            
            if (!$gateway) {
                return response()->json(['error' => 'No active SMS gateway found'], 400);
            }

            // Send SMS
            $result = $gateway->send($request->phone_number, $request->message);

            // Log SMS
            $log = SmsLog::create([
                'phone_number' => $request->phone_number,
                'message' => $request->message,
                'template_id' => $request->template_id,
                'gateway' => $gateway->provider,
                'status' => $result['success'] ? 'sent' : 'failed',
                'response' => json_encode($result),
                'sms_count' => $this->countSms($request->message),
                'cost' => $this->calculateCost($this->countSms($request->message)),
                'purpose' => $request->purpose ?? 'custom',
                'sent_by' => auth()->id(),
                'sent_at' => now()
            ]);

            return response()->json([
                'success' => true,
                'message' => 'SMS sent successfully',
                'log' => $log
            ]);

        } catch (\Exception $e) {
            return response()->json(['error' => $e->getMessage()], 500);
        }
    }

    /**
     * Send bulk SMS
     */
    public function sendBulk(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'recipient_type' => 'required|string',
            'class_id' => 'required_if:recipient_type,class|exists:classes,id',
            'template_id' => 'nullable|exists:sms_templates,id',
            'message' => 'required_without:template_id|string|max:160',
            'schedule' => 'nullable|date|after:now'
        ]);

        if ($validator->fails()) {
            return redirect()->back()
                           ->withErrors($validator)
                           ->withInput();
        }

        try {
            // Get recipients based on type
            $recipients = $this->getRecipients($request);

            if (empty($recipients)) {
                return redirect()->back()
                               ->with('error', 'কোনো প্রাপক খুঁজে পাওয়া যায়নি');
            }

            // Get template if selected
            $message = $request->message;
            if ($request->template_id) {
                $template = SmsTemplate::find($request->template_id);
                $message = $template->message;
            }

            // Schedule or send immediately
            if ($request->schedule) {
                $schedule = SmsSchedule::create([
                    'name' => $request->name ?? 'Bulk SMS',
                    'recipient_type' => $request->recipient_type,
                    'recipients' => $recipients,
                    'template_id' => $request->template_id,
                    'custom_message' => $message,
                    'scheduled_at' => $request->schedule,
                    'status' => 'pending',
                    'created_by' => auth()->id()
                ]);

                return redirect()->route('sms.schedules')
                               ->with('success', 'SMS scheduled successfully');
            } else {
                // Send immediately
                $this->processBulkSms($recipients, $message, $request->template_id);
                
                return redirect()->route('sms.index')
                               ->with('success', 'Bulk SMS sent successfully');
            }

        } catch (\Exception $e) {
            return redirect()->back()
                           ->with('error', 'Failed to send SMS: ' . $e->getMessage())
                           ->withInput();
        }
    }

    /**
     * Get recipients based on type
     */
    private function getRecipients($request)
    {
        $recipients = [];

        switch ($request->recipient_type) {
            case 'all_students':
                $students = Student::where('status', 1)->get();
                foreach ($students as $student) {
                    if ($student->phone) {
                        $recipients[] = [
                            'phone' => $student->phone,
                            'name' => $student->name_bn,
                            'type' => 'student',
                            'id' => $student->id
                        ];
                    }
                }
                break;

            case 'all_teachers':
                $teachers = Teacher::where('status', 'active')->get();
                foreach ($teachers as $teacher) {
                    if ($teacher->phone) {
                        $recipients[] = [
                            'phone' => $teacher->phone,
                            'name' => $teacher->name_bn,
                            'type' => 'teacher',
                            'id' => $teacher->id
                        ];
                    }
                }
                break;

            case 'class':
                $students = Student::where('class_id', $request->class_id)
                                  ->where('status', 1)
                                  ->get();
                foreach ($students as $student) {
                    if ($student->phone) {
                        $recipients[] = [
                            'phone' => $student->phone,
                            'name' => $student->name_bn,
                            'type' => 'student',
                            'id' => $student->id
                        ];
                    }
                }
                break;

            case 'individual':
                if ($request->has('recipients_list')) {
                    $recipients = json_decode($request->recipients_list, true);
                }
                break;
        }

        return $recipients;
    }

    /**
     * Process bulk SMS
     */
    private function processBulkSms($recipients, $message, $templateId = null)
    {
        $gateway = SmsGateway::getDefault();
        $successCount = 0;
        $failedCount = 0;

        foreach ($recipients as $recipient) {
            try {
                $personalizedMessage = $this->personalizeMessage($message, $recipient);
                
                $result = $gateway->send($recipient['phone'], $personalizedMessage);

                SmsLog::create([
                    'phone_number' => $recipient['phone'],
                    'message' => $personalizedMessage,
                    'template_id' => $templateId,
                    'gateway' => $gateway->provider,
                    'status' => $result['success'] ? 'sent' : 'failed',
                    'response' => json_encode($result),
                    'sms_count' => $this->countSms($personalizedMessage),
                    'cost' => $this->calculateCost($this->countSms($personalizedMessage)),
                    'purpose' => 'bulk',
                    'reference_id' => $recipient['id'] ?? null,
                    'reference_type' => $recipient['type'] ?? null,
                    'sent_by' => auth()->id(),
                    'sent_at' => now()
                ]);

                if ($result['success']) {
                    $successCount++;
                } else {
                    $failedCount++;
                }

                // Rate limiting
                usleep(500000); // 0.5 seconds delay

            } catch (\Exception $e) {
                $failedCount++;
            }
        }

        return ['success' => $successCount, 'failed' => $failedCount];
    }

    /**
     * Personalize message with recipient data
     */
    private function personalizeMessage($message, $recipient)
    {
        $replacements = [
            '{name}' => $recipient['name'] ?? '',
            '{phone}' => $recipient['phone'] ?? '',
            '{institution_name}' => config('app.name', 'Our School')
        ];

        return str_replace(array_keys($replacements), array_values($replacements), $message);
    }

    /**
     * Send fee reminder SMS
     */
    public function sendFeeReminder(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'class_id' => 'nullable|exists:classes,id',
            'month' => 'required|integer|between:1,12',
            'year' => 'required|integer'
        ]);

        if ($validator->fails()) {
            return redirect()->back()
                           ->withErrors($validator)
                           ->withInput();
        }

        $query = Fee::with('student')
                   ->where('payment_status', 'unpaid')
                   ->whereMonth('month_year', $request->month)
                   ->whereYear('month_year', $request->year);

        if ($request->class_id) {
            $query->where('class_id', $request->class_id);
        }

        $fees = $query->get();

        if ($fees->isEmpty()) {
            return redirect()->back()
                           ->with('info', 'No pending fees found for reminder');
        }

        $template = SmsTemplate::where('purpose', 'fee_payment')->first();

        if (!$template) {
            return redirect()->back()
                           ->with('error', 'Fee reminder template not found');
        }

        $recipients = [];
        foreach ($fees as $fee) {
            if ($fee->student && $fee->student->phone) {
                $recipients[] = [
                    'phone' => $fee->student->phone,
                    'name' => $fee->student->name_bn,
                    'type' => 'student',
                    'id' => $fee->student->id,
                    'data' => [
                        'amount' => $fee->due_amount,
                        'month' => $fee->month_name,
                        'due' => $fee->due_amount
                    ]
                ];
            }
        }

        // Customize message for each recipient
        foreach ($recipients as $recipient) {
            $message = $template->parse([
                'student_name' => $recipient['name'],
                'institution_name' => config('app.name'),
                'month' => $recipient['data']['month'],
                'amount' => $recipient['data']['amount'],
                'due' => $recipient['data']['due']
            ]);

            // Send SMS (simplified)
            $gateway = SmsGateway::getDefault();
            $gateway->send($recipient['phone'], $message);
        }

        return redirect()->back()
                       ->with('success', 'Fee reminders sent to ' . count($recipients) . ' students');
    }

    /**
     * Send exam result SMS
     */
    public function sendExamResult(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'exam_id' => 'required|exists:exams,id',
            'class_id' => 'required|exists:classes,id'
        ]);

        if ($validator->fails()) {
            return redirect()->back()
                           ->withErrors($validator)
                           ->withInput();
        }

        $results = Result::with('student')
                        ->where('exam_id', $request->exam_id)
                        ->where('class_id', $request->class_id)
                        ->get()
                        ->groupBy('student_id');

        $template = SmsTemplate::where('purpose', 'exam_result')->first();

        if (!$template) {
            return redirect()->back()
                           ->with('error', 'Exam result template not found');
        }

        $sent = 0;
        foreach ($results as $studentId => $studentResults) {
            $student = $studentResults->first()->student;
            
            if (!$student->phone) continue;

            $gpa = $studentResults->avg('grade_point');
            $grade = $this->calculateGrade($gpa);

            $message = $template->parse([
                'student_name' => $student->name_bn,
                'exam_name' => $studentResults->first()->exam_name,
                'gpa' => number_format($gpa, 2),
                'grade' => $grade,
                'result_url' => route('results.show', $student->id)
            ]);

            $gateway = SmsGateway::getDefault();
            $gateway->send($student->phone, $message);
            $sent++;
        }

        return redirect()->back()
                       ->with('success', 'Exam results sent to ' . $sent . ' students');
    }

    /**
     * SMS templates management
     */
    public function templates()
    {
        $templates = SmsTemplate::with('creator')->get();
        $purposes = SmsLog::getPurposeTypes();

        return view('sms.templates', compact('templates', 'purposes'));
    }

    /**
     * Store SMS template
     */
    public function storeTemplate(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'name' => 'required|string|max:255',
            'purpose' => 'required|string',
            'message' => 'required|string|max:500',
            'variables' => 'nullable|array'
        ]);

        if ($validator->fails()) {
            return redirect()->back()
                           ->withErrors($validator)
                           ->withInput();
        }

        try {
            SmsTemplate::create([
                'name' => $request->name,
                'purpose' => $request->purpose,
                'message' => $request->message,
                'variables' => $request->variables,
                'created_by' => auth()->id()
            ]);

            return redirect()->route('sms.templates')
                           ->with('success', 'Template created successfully');

        } catch (\Exception $e) {
            return redirect()->back()
                           ->with('error', 'Failed to create template');
        }
    }

    /**
     * SMS gateways management
     */
    public function gateways()
    {
        $gateways = SmsGateway::all();
        $providers = SmsGateway::getProviders();

        return view('sms.gateways', compact('gateways', 'providers'));
    }

    /**
     * Store SMS gateway
     */
    public function storeGateway(Request $request)
    {
        $validator = Validator::make($request->all(), [
            'name' => 'required|string|max:255',
            'provider' => 'required|string',
            'api_url' => 'nullable|url',
            'api_key' => 'nullable|string',
            'secret_key' => 'nullable|string',
            'sender_id' => 'nullable|string|max:11',
            'username' => 'nullable|string',
            'password' => 'nullable|string'
        ]);

        if ($validator->fails()) {
            return redirect()->back()
                           ->withErrors($validator)
                           ->withInput();
        }

        try {
            // If set as default, remove default from others
            if ($request->is_default) {
                SmsGateway::where('is_default', true)->update(['is_default' => false]);
            }

            SmsGateway::create($request->all());

            return redirect()->route('sms.gateways')
                           ->with('success', 'Gateway added successfully');

        } catch (\Exception $e) {
            return redirect()->back()
                           ->with('error', 'Failed to add gateway');
        }
    }

    /**
     * Test SMS gateway
     */
    public function testGateway(Request $request, $id)
    {
        $gateway = SmsGateway::findOrFail($id);

        $validator = Validator::make($request->all(), [
            'test_phone' => 'required|string|max:20',
            'test_message' => 'required|string|max:160'
        ]);

        if ($validator->fails()) {
            return response()->json(['errors' => $validator->errors()], 422);
        }

        try {
            $result = $gateway->send($request->test_phone, $request->test_message);

            return response()->json([
                'success' => $result['success'],
                'response' => $result
            ]);

        } catch (\Exception $e) {
            return response()->json(['error' => $e->getMessage()], 500);
        }
    }

    /**
     * SMS schedules
     */
    public function schedules()
    {
        $schedules = SmsSchedule::with('template', 'creator')
                                ->orderBy('scheduled_at', 'desc')
                                ->paginate(20);

        return view('sms.schedules', compact('schedules'));
    }

    /**
     * Cancel schedule
     */
    public function cancelSchedule($id)
    {
        $schedule = SmsSchedule::findOrFail($id);

        if ($schedule->status == 'pending') {
            $schedule->update(['status' => 'cancelled']);
            return redirect()->back()
                           ->with('success', 'Schedule cancelled');
        }

        return redirect()->back()
                       ->with('error', 'Cannot cancel this schedule');
    }

    /**
     * SMS reports
     */
    public function reports(Request $request)
    {
        $query = SmsLog::with('template', 'sender');

        if ($request->from_date) {
            $query->whereDate('sent_at', '>=', $request->from_date);
        }

        if ($request->to_date) {
            $query->whereDate('sent_at', '<=', $request->to_date);
        }

        if ($request->status) {
            $query->where('status', $request->status);
        }

        if ($request->purpose) {
            $query->where('purpose', $request->purpose);
        }

        $logs = $query->orderBy('sent_at', 'desc')->paginate(50);

        $summary = [
            'total' => $logs->total(),
            'success' => $query->where('status', 'sent')->count(),
            'failed' => $query->where('status', 'failed')->count(),
            'total_cost' => $query->sum('cost'),
            'total_sms' => $query->sum('sms_count')
        ];

        return view('sms.reports', compact('logs', 'summary', 'request'));
    }

    /**
     * Helper: Count SMS
     */
    private function countSms($message)
    {
        $length = strlen($message);
        if ($length <= 160) return 1;
        if ($length <= 306) return 2;
        return ceil($length / 153);
    }

    /**
     * Helper: Calculate cost
     */
    private function calculateCost($smsCount)
    {
        // 0.25 টাকা per SMS (adjust as needed)
        return $smsCount * 0.25;
    }

    /**
     * Helper: Calculate success rate
     */
    private function calculateSuccessRate()
    {
        $total = SmsLog::whereDate('created_at', today())->count();
        if ($total == 0) return 100;

        $success = SmsLog::whereDate('created_at', today())
                        ->where('status', 'sent')
                        ->count();

        return round(($success / $total) * 100, 2);
    }

    /**
     * Helper: Get balance
     */
    private function getBalance()
    {
        $gateway = SmsGateway::getDefault();
        return $gateway ? $gateway->balance : 0;
    }

    /**
     * Helper: Calculate grade from GPA
     */
    private function calculateGrade($gpa)
    {
        if ($gpa >= 5) return 'A+';
        if ($gpa >= 4) return 'A';
        if ($gpa >= 3.5) return 'A-';
        if ($gpa >= 3) return 'B';
        if ($gpa >= 2) return 'C';
        if ($gpa >= 1) return 'D';
        return 'F';
    }
}