<?php

namespace App\Http\Controllers;

use App\Models\Store;
use App\Models\Menu;
use App\Models\QadSyncLog;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Exception;

class QadSyncController extends Controller
{
    private $baseUrl;
    private $apiKey;
    private $timeout;

    public function __construct()
    {
        parent::__construct();
        $this->baseUrl = config('services.qad.base_url', 'https://api.qad.example.com');
        $this->apiKey = config('services.qad.api_key', 'dummy-api-key');
        $this->timeout = config('services.qad.timeout', 30);
    }

    /**
     * Show QAD sync dashboard
     */
    public function index()
    {
        return view('qad-sync.index', [
            'variables' => $this->variables([
                'judul' => 'QAD Synchronization'
            ])
        ]);
    }

    /**
     * Test QAD connection
     */
    public function testConnection()
    {
        try {
            // Simulate connection test
            return response()->json([
                'success' => true,
                'message' => 'QAD API connection successful (simulated)',
                'timestamp' => now()->toISOString(),
                'version' => '1.0.0'
            ]);

            // Real implementation when QAD is ready:
            // $response = Http::timeout(10)
            //     ->withHeaders([
            //         'Authorization' => 'Bearer ' . $this->apiKey,
            //     ])
            //     ->get($this->baseUrl . '/api/health');

            // if ($response->successful()) {
            //     return response()->json($response->json());
            // }

            // throw new Exception('Connection failed: ' . $response->status());

        } catch (Exception $e) {
            Log::error('QAD Connection Test Error: ' . $e->getMessage());
            
            return response()->json([
                'success' => false,
                'message' => 'QAD API connection failed: ' . $e->getMessage(),
                'timestamp' => now()->toISOString()
            ], 500);
        }
    }

    /**
     * Sync stores from QAD
     */
    public function syncStores()
    {
        $syncLog = QadSyncLog::startSync(QadSyncLog::TYPE_STORES);
        
        try {
            $startTime = microtime(true);
            $response = $this->getStoresFromQad();
            $qadResponseTime = (microtime(true) - $startTime) * 1000; // Convert to milliseconds
            
            if (!$response['success']) {
                throw new Exception('QAD API returned error for stores');
            }

            $syncResult = [
                'success' => true,
                'total_from_qad' => $response['total'],
                'inserted' => 0,
                'updated' => 0,
                'errors' => [],
                'details' => []
            ];

            foreach ($response['data'] as $qadStore) {
                // Use individual transactions for each store to prevent rollback cascade
                DB::beginTransaction();
                
                try {
                    // Check if store exists by QAD code (we'll use description field to store QAD code)
                    $existingStore = Store::where('description', 'like', '%QAD:' . $qadStore['qad_code'] . '%')
                        ->where('delete_flag', 0)
                        ->first();

                    $storeData = [
                        'store_type' => $qadStore['store_type'],
                        'document_type' => $qadStore['document_type'],
                        'name' => $qadStore['name'],
                        'address' => $qadStore['address'],
                        'pic' => $qadStore['pic'],
                        'pic_phone' => $qadStore['pic_phone'],
                        'pic_email' => $qadStore['pic_email'],
                        'description' => $qadStore['description'] . ' [QAD:' . $qadStore['qad_code'] . ']',
                        'bom_di' => $qadStore['bom_di'],
                        'bom_to' => $qadStore['bom_to'],
                        'status' => $qadStore['status'],
                        'inactive_date' => $qadStore['inactive_date'],
                        'updated_by' => auth()->id() ?? 1,
                    ];

                    if ($existingStore) {
                        // Update existing store
                        $existingStore->update($storeData);
                        $syncResult['updated']++;
                        $syncResult['details'][] = [
                            'action' => 'updated',
                            'qad_code' => $qadStore['qad_code'],
                            'name' => $qadStore['name'],
                            'local_code' => $existingStore->code
                        ];
                        
                        Log::info('Store updated from QAD', [
                            'qad_code' => $qadStore['qad_code'],
                            'local_code' => $existingStore->code,
                            'name' => $qadStore['name']
                        ]);
                    } else {
                        // Insert new store
                        $storeData['created_by'] = auth()->id() ?? 1;
                        $newStore = Store::create($storeData);
                        $syncResult['inserted']++;
                        $syncResult['details'][] = [
                            'action' => 'inserted',
                            'qad_code' => $qadStore['qad_code'],
                            'name' => $qadStore['name'],
                            'local_code' => $newStore->code
                        ];
                        
                        Log::info('Store inserted from QAD', [
                            'qad_code' => $qadStore['qad_code'],
                            'local_code' => $newStore->code,
                            'name' => $qadStore['name']
                        ]);
                    }

                    DB::commit();

                } catch (Exception $e) {
                    DB::rollback();
                    $syncResult['errors'][] = [
                        'qad_code' => $qadStore['qad_code'] ?? 'unknown',
                        'error' => $e->getMessage()
                    ];
                    Log::error('Error syncing store from QAD', [
                        'qad_code' => $qadStore['qad_code'] ?? 'unknown',
                        'error' => $e->getMessage()
                    ]);
                }
            }

            // Determine overall success based on whether we had any successful operations
            $syncResult['success'] = ($syncResult['inserted'] + $syncResult['updated']) > 0 || count($syncResult['errors']) == 0;
            
            if (count($syncResult['errors']) > 0 && ($syncResult['inserted'] + $syncResult['updated']) > 0) {
                $syncResult['message'] = "Partial sync completed: {$syncResult['inserted']} inserted, {$syncResult['updated']} updated, " . count($syncResult['errors']) . " errors";
            } else if (count($syncResult['errors']) > 0) {
                $syncResult['message'] = "Sync failed: " . count($syncResult['errors']) . " errors occurred";
                $syncResult['success'] = false;
            } else {
                $syncResult['message'] = "Sync completed: {$syncResult['inserted']} inserted, {$syncResult['updated']} updated";
            }
            
            // Complete sync log
            $syncLog->completeSync($syncResult, $qadResponseTime, $response['request_details'] ?? null);
            
            $statusCode = $syncResult['success'] ? 200 : 500;
            return response()->json($syncResult, $statusCode);

        } catch (Exception $e) {
            Log::error('Store sync failed', ['error' => $e->getMessage()]);
            
            $errorResult = [
                'success' => false,
                'message' => 'Store sync failed: ' . $e->getMessage(),
                'total_from_qad' => 0,
                'inserted' => 0,
                'updated' => 0,
                'errors' => [['error' => $e->getMessage()]]
            ];
            
            $syncLog->completeSync($errorResult);
            
            return response()->json($errorResult, 500);
        }
    }

    /**
     * Sync menus from QAD
     */
    public function syncMenus()
    {
        $syncLog = QadSyncLog::startSync(QadSyncLog::TYPE_MENUS);
        
        try {
            $startTime = microtime(true);
            $response = $this->getMenusFromQad();
            $qadResponseTime = (microtime(true) - $startTime) * 1000; // Convert to milliseconds
            
            if (!$response['success']) {
                throw new Exception('QAD API returned error for menus');
            }

            $syncResult = [
                'success' => true,
                'total_from_qad' => $response['total'],
                'inserted' => 0,
                'updated' => 0,
                'errors' => [],
                'details' => []
            ];

            foreach ($response['data'] as $qadMenu) {
                // Use individual transactions for each menu to prevent rollback cascade
                DB::beginTransaction();
                
                try {
                    // Check if menu exists by QAD code first (primary check)
                    $existingMenu = Menu::where('description', 'like', '%QAD:' . $qadMenu['qad_code'] . '%')
                        ->where('delete_flag', 0)
                        ->first();

                    // If not found by QAD code, check by plu_code (to handle duplicates)
                    if (!$existingMenu) {
                        $existingMenu = Menu::where('plu_code', $qadMenu['plu_code'])
                            ->where('delete_flag', 0)
                            ->first();
                    }

                    $menuData = [
                        'name' => $qadMenu['name'],
                        'menu_group' => $qadMenu['menu_group'],
                        'plu_code' => $qadMenu['plu_code'],
                        'category' => $qadMenu['category'],
                        'price' => $qadMenu['price'],
                        'description' => $qadMenu['description'] . ' [QAD:' . $qadMenu['qad_code'] . ']',
                        'is_active' => $qadMenu['is_active'],
                        'updated_by' => auth()->id() ?? 1,
                    ];

                    if ($existingMenu) {
                        // Update existing menu
                        $existingMenu->update($menuData);
                        $syncResult['updated']++;
                        $syncResult['details'][] = [
                            'action' => 'updated',
                            'qad_code' => $qadMenu['qad_code'],
                            'name' => $qadMenu['name'],
                            'local_code' => $existingMenu->code,
                            'price' => $qadMenu['price']
                        ];
                        
                        Log::info('Menu updated from QAD', [
                            'qad_code' => $qadMenu['qad_code'],
                            'local_code' => $existingMenu->code,
                            'name' => $qadMenu['name']
                        ]);
                    } else {
                        // Insert new menu
                        $menuData['created_by'] = auth()->id() ?? 1;
                        $newMenu = Menu::create($menuData);
                        $syncResult['inserted']++;
                        $syncResult['details'][] = [
                            'action' => 'inserted',
                            'qad_code' => $qadMenu['qad_code'],
                            'name' => $qadMenu['name'],
                            'local_code' => $newMenu->code,
                            'price' => $qadMenu['price']
                        ];
                        
                        Log::info('Menu inserted from QAD', [
                            'qad_code' => $qadMenu['qad_code'],
                            'local_code' => $newMenu->code,
                            'name' => $qadMenu['name']
                        ]);
                    }

                    DB::commit();

                } catch (Exception $e) {
                    DB::rollback();
                    $syncResult['errors'][] = [
                        'qad_code' => $qadMenu['qad_code'] ?? 'unknown',
                        'error' => $e->getMessage()
                    ];
                    Log::error('Error syncing menu from QAD', [
                        'qad_code' => $qadMenu['qad_code'] ?? 'unknown',
                        'error' => $e->getMessage()
                    ]);
                }
            }

            // Determine overall success based on whether we had any successful operations
            $syncResult['success'] = ($syncResult['inserted'] + $syncResult['updated']) > 0 || count($syncResult['errors']) == 0;
            
            if (count($syncResult['errors']) > 0 && ($syncResult['inserted'] + $syncResult['updated']) > 0) {
                $syncResult['message'] = "Partial sync completed: {$syncResult['inserted']} inserted, {$syncResult['updated']} updated, " . count($syncResult['errors']) . " errors";
            } else if (count($syncResult['errors']) > 0) {
                $syncResult['message'] = "Sync failed: " . count($syncResult['errors']) . " errors occurred";
                $syncResult['success'] = false;
            } else {
                $syncResult['message'] = "Sync completed: {$syncResult['inserted']} inserted, {$syncResult['updated']} updated";
            }
            
            // Complete sync log
            $syncLog->completeSync($syncResult, $qadResponseTime, $response['request_details'] ?? null);
            
            $statusCode = $syncResult['success'] ? 200 : 500;
            return response()->json($syncResult, $statusCode);

        } catch (Exception $e) {
            Log::error('Menu sync failed', ['error' => $e->getMessage()]);
            
            $errorResult = [
                'success' => false,
                'message' => 'Menu sync failed: ' . $e->getMessage(),
                'total_from_qad' => 0,
                'inserted' => 0,
                'updated' => 0,
                'errors' => [['error' => $e->getMessage()]]
            ];
            
            $syncLog->completeSync($errorResult);
            
            return response()->json($errorResult, 500);
        }
    }

    /**
     * Sync all data from QAD
     */
    public function syncAll()
    {
        $syncLog = QadSyncLog::startSync(QadSyncLog::TYPE_ALL);
        
        try {
            // Call individual sync methods and get their responses
            $storeResponse = $this->syncStores();
            $menuResponse = $this->syncMenus();
            
            // Extract data from responses
            $storeResult = $storeResponse->getData(true);
            $menuResult = $menuResponse->getData(true);

            $result = [
                'success' => $storeResult['success'] && $menuResult['success'],
                'stores' => $storeResult,
                'menus' => $menuResult,
                'summary' => [
                    'total_inserted' => $storeResult['inserted'] + $menuResult['inserted'],
                    'total_updated' => $storeResult['updated'] + $menuResult['updated'],
                    'total_errors' => count($storeResult['errors']) + count($menuResult['errors'])
                ]
            ];
            
            // Complete sync log
            $syncLog->completeSync($result);
            
            $statusCode = $result['success'] ? 200 : 500;
            return response()->json($result, $statusCode);
            
        } catch (Exception $e) {
            $errorResult = [
                'success' => false,
                'message' => 'Full sync failed: ' . $e->getMessage(),
                'stores' => [
                    'success' => false,
                    'message' => 'Not executed due to error',
                    'inserted' => 0,
                    'updated' => 0,
                    'errors' => []
                ],
                'menus' => [
                    'success' => false,
                    'message' => 'Not executed due to error',
                    'inserted' => 0,
                    'updated' => 0,
                    'errors' => []
                ],
                'summary' => [
                    'total_inserted' => 0,
                    'total_updated' => 0,
                    'total_errors' => 1
                ]
            ];
            
            $syncLog->completeSync($errorResult);
            
            return response()->json($errorResult, 500);
        }
    }

    /**
     * Get sync history/logs
     */
    public function getSyncHistory()
    {
        try {
            $logs = QadSyncLog::getRecentLogs(100);
            $statistics = QadSyncLog::getSyncStatistics(30);
            
            return response()->json([
                'success' => true,
                'logs' => $logs->map(function($log) {
                    return [
                        'id' => $log->id,
                        'sync_type' => $log->sync_type,
                        'status' => $log->status,
                        'started_at' => $log->started_at->format('Y-m-d H:i:s'),
                        'completed_at' => $log->completed_at ? $log->completed_at->format('Y-m-d H:i:s') : null,
                        'duration_seconds' => $log->duration_seconds,
                        'total_from_qad' => $log->total_from_qad,
                        'total_inserted' => $log->total_inserted,
                        'total_updated' => $log->total_updated,
                        'total_errors' => $log->total_errors,
                        'trigger_type' => $log->trigger_type,
                        'triggered_by' => $log->triggeredBy ? $log->triggeredBy->name : 'System',
                        'error_details' => $log->error_details,
                        'sync_details' => $log->sync_details,
                        'request_details' => $log->request_details,
                        'qad_response_time' => $log->qad_response_time,
                    ];
                }),
                'statistics' => $statistics,
                'total' => $logs->count()
            ]);
            
        } catch (Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Failed to retrieve sync history: ' . $e->getMessage(),
                'logs' => [],
                'statistics' => [],
                'total' => 0
            ], 500);
        }
    }

    /**
     * Get sync statistics
     */
    public function getSyncStatistics()
    {
        try {
            $statistics = QadSyncLog::getSyncStatistics(30);
            
            return response()->json([
                'success' => true,
                'statistics' => $statistics
            ]);
            
        } catch (Exception $e) {
            return response()->json([
                'success' => false,
                'message' => 'Failed to retrieve sync statistics: ' . $e->getMessage(),
                'statistics' => []
            ], 500);
        }
    }

    /**
     * Get stores from QAD API
     */
    private function getStoresFromQad()
    {
        $requestDetails = [
            'method' => 'GET',
            'url' => $this->baseUrl . '/api/stores',
            'headers' => [
                'Authorization' => 'Bearer ' . substr($this->apiKey, 0, 10) . '...',
                'Content-Type' => 'application/json',
            ],
            'timeout' => $this->timeout,
            'timestamp' => now()->toISOString()
        ];

        try {
            // Simulate QAD API response for now
            $response = $this->simulateStoresResponse();
            $response['request_details'] = $requestDetails;
            return $response;
            
            // Real implementation when QAD is ready:
            // $response = Http::timeout($this->timeout)
            //     ->withHeaders([
            //         'Authorization' => 'Bearer ' . $this->apiKey,
            //         'Content-Type' => 'application/json',
            //     ])
            //     ->get($this->baseUrl . '/api/stores');

            // if ($response->successful()) {
            //     $result = $response->json();
            //     $result['request_details'] = $requestDetails;
            //     return $result;
            // }

            // throw new Exception('QAD API Error: ' . $response->body());

        } catch (Exception $e) {
            Log::error('QAD Store API Error: ' . $e->getMessage());
            throw $e;
        }
    }

    /**
     * Get menus from QAD API
     */
    private function getMenusFromQad()
    {
        $requestDetails = [
            'method' => 'GET',
            'url' => $this->baseUrl . '/api/menus',
            'headers' => [
                'Authorization' => 'Bearer ' . substr($this->apiKey, 0, 10) . '...',
                'Content-Type' => 'application/json',
            ],
            'timeout' => $this->timeout,
            'timestamp' => now()->toISOString()
        ];

        try {
            // Simulate QAD API response for now
            $response = $this->simulateMenusResponse();
            $response['request_details'] = $requestDetails;
            return $response;
            
            // Real implementation when QAD is ready:
            // $response = Http::timeout($this->timeout)
            //     ->withHeaders([
            //         'Authorization' => 'Bearer ' . $this->apiKey,
            //         'Content-Type' => 'application/json',
            //     ])
            //     ->get($this->baseUrl . '/api/menus');

            // if ($response->successful()) {
            //     $result = $response->json();
            //     $result['request_details'] = $requestDetails;
            //     return $result;
            // }

            // throw new Exception('QAD API Error: ' . $response->body());

        } catch (Exception $e) {
            Log::error('QAD Menu API Error: ' . $e->getMessage());
            throw $e;
        }
    }

    /**
     * Simulate QAD Stores Response
     */
    private function simulateStoresResponse()
    {
        return [
            'success' => true,
            'data' => [
                [
                    'qad_code' => 'QAD001',
                    'store_type' => 'Restaurant',
                    'document_type' => 'LSM',
                    'name' => 'Bakmi GM Senayan City',
                    'address' => 'Senayan City Mall, Lt. 6, Jakarta Selatan',
                    'pic' => 'John Doe',
                    'pic_phone' => '081234567890',
                    'pic_email' => 'senayan@bakmigm.com',
                    'description' => 'Outlet Senayan City - Premium Location',
                    'bom_di' => 'BOM001',
                    'bom_to' => 'BOM002',
                    'status' => 'Active',
                    'inactive_date' => null,
                    'last_updated' => '2026-01-07 10:00:00'
                ],
                [
                    'qad_code' => 'QAD002',
                    'store_type' => 'Restaurant',
                    'document_type' => 'LSM',
                    'name' => 'Bakmi GM Plaza Indonesia',
                    'address' => 'Plaza Indonesia, Lt. 4, Jakarta Pusat',
                    'pic' => 'Jane Smith',
                    'pic_phone' => '081234567891',
                    'pic_email' => 'plazaindonesia@bakmigm.com',
                    'description' => 'Outlet Plaza Indonesia - Central Location',
                    'bom_di' => 'BOM003',
                    'bom_to' => 'BOM004',
                    'status' => 'Active',
                    'inactive_date' => null,
                    'last_updated' => '2026-01-07 10:00:00'
                ],
                [
                    'qad_code' => 'QAD003',
                    'store_type' => 'Restaurant',
                    'document_type' => 'LSM',
                    'name' => 'Bakmi GM Grand Indonesia',
                    'address' => 'Grand Indonesia Mall, Lt. 3A, Jakarta Pusat',
                    'pic' => 'Bob Wilson',
                    'pic_phone' => '081234567892',
                    'pic_email' => 'grandindonesia@bakmigm.com',
                    'description' => 'Outlet Grand Indonesia - Shopping Mall',
                    'bom_di' => 'BOM005',
                    'bom_to' => 'BOM006',
                    'status' => 'Active',
                    'inactive_date' => null,
                    'last_updated' => '2026-01-07 10:00:00'
                ]
            ],
            'total' => 3,
            'timestamp' => now()->toISOString()
        ];
    }

    /**
     * Simulate QAD Menus Response
     */
    private function simulateMenusResponse()
    {
        return [
            'success' => true,
            'data' => [
                [
                    'qad_code' => 'MENU001',
                    'name' => 'Bakmi GM Special',
                    'menu_group' => 'Bakmi',
                    'plu_code' => 'PLU001',
                    'category' => 'Main Course',
                    'price' => 45000.00,
                    'description' => 'Bakmi GM dengan topping lengkap',
                    'is_active' => true,
                    'last_updated' => '2026-01-07 10:00:00'
                ],
                [
                    'qad_code' => 'MENU002',
                    'name' => 'Bakmi GM Ayam',
                    'menu_group' => 'Bakmi',
                    'plu_code' => 'PLU002',
                    'category' => 'Main Course',
                    'price' => 38000.00,
                    'description' => 'Bakmi GM dengan ayam',
                    'is_active' => true,
                    'last_updated' => '2026-01-07 10:00:00'
                ],
                [
                    'qad_code' => 'MENU003',
                    'name' => 'Bakmi GM Babi',
                    'menu_group' => 'Bakmi',
                    'plu_code' => 'PLU003',
                    'category' => 'Main Course',
                    'price' => 42000.00,
                    'description' => 'Bakmi GM dengan babi',
                    'is_active' => true,
                    'last_updated' => '2026-01-07 10:00:00'
                ],
                [
                    'qad_code' => 'MENU004',
                    'name' => 'Es Teh Manis',
                    'menu_group' => 'Beverages',
                    'plu_code' => 'PLU004',
                    'category' => 'Drinks',
                    'price' => 8000.00,
                    'description' => 'Es teh manis segar',
                    'is_active' => true,
                    'last_updated' => '2026-01-07 10:00:00'
                ],
                [
                    'qad_code' => 'MENU005',
                    'name' => 'Pangsit Goreng',
                    'menu_group' => 'Appetizer',
                    'plu_code' => 'PLU005',
                    'category' => 'Appetizer',
                    'price' => 25000.00,
                    'description' => 'Pangsit goreng crispy',
                    'is_active' => true,
                    'last_updated' => '2026-01-07 10:00:00'
                ]
            ],
            'total' => 5,
            'timestamp' => now()->toISOString()
        ];
    }

    private function variables($variables = null)
    {
        $variables['header_routes'] = ' 
								<li class="breadcrumb-item">Configurations</li>  
								<li class="breadcrumb-item active">QAD Synchronization</li>
							 ';
        return $variables;
    }
}