<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Str;
use Maatwebsite\Excel\Facades\Excel;
use App\Exports\SongsExport;
use App\Exports\ArtistsExport;
use App\Exports\DemandsExport;
use App\Imports\SongsImport;
use App\Imports\ArtistsImport;
use App\Artist;
use App\Song;

class ImportExportController extends Controller
{
    public function __construct()
    {
        $this->middleware('admin');
    }

    public function index()
    {
        return view('admin.import-export');
    }

    public function export($type, $format)
    {
        ini_set('memory_limit', '1G');
        set_time_limit(0);
        $ext = strtolower($format);

        // JSON export
        if ($ext === 'json') {
            return $this->exportJson($type);
        }

        $headers = ['Content-Type' => 'text/csv; charset=UTF-8', 'Content-Disposition' => "attachment; filename={$type}.csv"];

        if ($ext !== 'csv') {
            $writerType = $ext === 'ods' ? \Maatwebsite\Excel\Excel::ODS : \Maatwebsite\Excel\Excel::XLSX;
            switch ($type) {
                case 'songs': return Excel::download(new SongsExport, "songs.{$ext}", $writerType);
                case 'artists': return Excel::download(new ArtistsExport, "artists.{$ext}", $writerType);
                case 'demands': return Excel::download(new DemandsExport, "demands.{$ext}", $writerType);
            }
            flash('نوع البيانات غير مدعوم')->error();
            return redirect('/admin/import-export');
        }

        switch ($type) {
            case 'songs':
                $columns = ['id','title','slug','artists','lyrics','views','created_at','updated_at'];
                $rows = \App\Song::with('artists')->cursor();
                $callback = function($song) { return [
                    $song->id,
                    $song->title,
                    $song->slug,
                    $song->artists->pluck('name')->implode(' / '),
                    str_replace(["\r","\n"], " | ", $song->lyrics),
                    $song->views,
                    $song->created_at,
                    $song->updated_at,
                ]; };
                break;
            case 'artists':
                $columns = ['id','name','slug','created_at','updated_at'];
                $rows = \App\Artist::cursor();
                $callback = function($artist) { return [$artist->id, $artist->name, $artist->slug, $artist->created_at, $artist->updated_at]; };
                break;
            case 'demands':
                $columns = ['id','user_id','song','artist','lyrics','type','is_read','created_at','updated_at'];
                $rows = \App\Demand::cursor();
                $callback = function($d) { return [$d->id, $d->user_id, $d->song, $d->artist, str_replace(["\r","\n"], " | ", $d->lyrics), $d->type, $d->is_read, $d->created_at, $d->updated_at]; };
                break;
            default:
                flash('نوع البيانات غير مدعوم')->error();
                return redirect('/admin/import-export');
        }

        $response = response()->stream(function() use ($columns, $rows, $callback) {
            $handle = fopen('php://output', 'w');
            fprintf($handle, chr(0xEF).chr(0xBB).chr(0xBF));
            fputcsv($handle, $columns);
            foreach ($rows as $row) {
                fputcsv($handle, $callback($row));
            }
            fclose($handle);
        }, 200, $headers);

        return $response;
    }

    public function import(Request $request)
    {
        $request->validate([
            'file' => 'required|file|mimes:csv,xlsx,xls,ods',
            'type' => 'required|in:songs,artists',
        ]);

        try {
            if ($request->type === 'songs') {
                Excel::import(new SongsImport, $request->file('file'));
                flash('تم استيراد الأغاني بنجاح')->success();
            } else {
                Excel::import(new ArtistsImport, $request->file('file'));
                flash('تم استيراد الفنانين بنجاح')->success();
            }
        } catch (\Exception $e) {
            flash('فشل الاستيراد: ' . $e->getMessage())->error();
        }

        return redirect('/admin/import-export');
    }

    private function exportJson($type)
    {
        $filename = $type . '.json';
        $headers = [
            'Content-Type' => 'application/json; charset=UTF-8',
            'Content-Disposition' => "attachment; filename={$filename}",
        ];

        return response()->stream(function () use ($type) {
            $handle = fopen('php://output', 'w');
            fwrite($handle, '[');
            $first = true;

            switch ($type) {
                case 'songs':
                    foreach (Song::with('artists')->cursor() as $song) {
                        if (!$first) fwrite($handle, ',');
                        $first = false;
                        fwrite($handle, json_encode([
                            'title'   => $song->title,
                            'lyrics'  => $song->lyrics,
                            'artist'  => $song->artists->pluck('name')->implode(' / '),
                            'views'   => (int) $song->views,
                        ], JSON_UNESCAPED_UNICODE));
                    }
                    break;
                case 'artists':
                    foreach (Artist::cursor() as $artist) {
                        if (!$first) fwrite($handle, ',');
                        $first = false;
                        fwrite($handle, json_encode([
                            'name' => $artist->name,
                        ], JSON_UNESCAPED_UNICODE));
                    }
                    break;
                case 'demands':
                    foreach (\App\Demand::cursor() as $d) {
                        if (!$first) fwrite($handle, ',');
                        $first = false;
                        fwrite($handle, json_encode([
                            'song'   => $d->song,
                            'artist' => $d->artist,
                            'lyrics' => $d->lyrics,
                            'type'   => $d->type,
                        ], JSON_UNESCAPED_UNICODE));
                    }
                    break;
            }

            fwrite($handle, ']');
            fclose($handle);
        }, 200, $headers);
    }

    public function importJson(Request $request)
    {
        $request->validate([
            'json_file' => 'required|file',
        ]);

        ini_set('memory_limit', '1G');
        set_time_limit(0);

        try {
            $content = file_get_contents($request->file('json_file')->getRealPath());
            $data = json_decode($content, true);

            if (json_last_error() !== JSON_ERROR_NONE) {
                flash('ملف JSON غير صالح: ' . json_last_error_msg())->error();
                return redirect('/admin/import-export');
            }

            // Normalize: support flat array or grouped format (e.g. {"Hijazi": [...], "Gulf": [...]})
            $entries = [];
            if (isset($data[0])) {
                // Flat array
                $entries = $data;
            } else {
                // Grouped by category/dialect
                foreach ($data as $group => $items) {
                    if (is_array($items)) {
                        foreach ($items as $item) {
                            $entries[] = $item;
                        }
                    }
                }
            }

            if (empty($entries)) {
                flash('لا توجد بيانات في ملف JSON.')->error();
                return redirect('/admin/import-export');
            }

            // Pre-load existing slugs for uniqueness
            $existingSlugs = [];
            foreach (DB::table('artists')->pluck('slug') as $s) $existingSlugs[$s] = true;
            foreach (DB::table('songs')->pluck('slug') as $s) $existingSlugs[$s] = true;

            $now = now();
            $newSongs = 0;
            $newArtists = 0;
            $skipped = 0;

            // Group entries by (artist, title) to combine lyrics
            $grouped = [];
            foreach ($entries as $entry) {
                $title  = trim($entry['title']  ?? $entry['Title']  ?? '');
                $artist = trim($entry['artist'] ?? $entry['Artist'] ?? $entry['Writer'] ?? $entry['writer'] ?? '');
                $lyrics = trim($entry['lyrics'] ?? $entry['Lyrics'] ?? '');
                $views  = (int)($entry['views']  ?? $entry['Views']  ?? 0);

                if (!$title) continue;

                $key = mb_strtolower($artist . '|||' . $title);
                if (!isset($grouped[$key])) {
                    $grouped[$key] = [
                        'title'  => $title,
                        'artist' => $artist,
                        'lyrics' => [],
                        'views'  => $views,
                    ];
                }
                $grouped[$key]['lyrics'][] = $lyrics;
            }

            // Insert in batches
            $batch = [];
            foreach ($grouped as $item) {
                $batch[] = $item;
                if (count($batch) >= 200) {
                    $result = $this->insertJsonBatch($batch, $existingSlugs, $now);
                    $newSongs   += $result['songs'];
                    $newArtists += $result['artists'];
                    $skipped    += $result['skipped'];
                    $batch = [];
                }
            }
            if (!empty($batch)) {
                $result = $this->insertJsonBatch($batch, $existingSlugs, $now);
                $newSongs   += $result['songs'];
                $newArtists += $result['artists'];
                $skipped    += $result['skipped'];
            }

            flash("تم استيراد JSON بنجاح: {$newSongs} أغنية جديدة، {$newArtists} فنان جديد" . ($skipped ? "، تم تخطي {$skipped} مكرر" : ''))->success();

        } catch (\Exception $e) {
            flash('فشل استيراد JSON: ' . $e->getMessage())->error();
        }

        return redirect('/admin/import-export');
    }

    private function insertJsonBatch(array $batch, array &$existingSlugs, $now)
    {
        $newSongs = 0;
        $newArtists = 0;
        $skipped = 0;

        DB::beginTransaction();
        try {
            foreach ($batch as $item) {
                $title  = $item['title'];
                $lyrics = implode("\n", $item['lyrics']);
                $views  = $item['views'];
                $artistName = $item['artist'];

                // Check if song exists
                $song = Song::where('title', $title)->first();
                if ($song) {
                    // Song exists - just link artist if needed
                    if ($artistName) {
                        $artist = Artist::where('name', $artistName)->first();
                        if (!$artist) {
                            $artist = new Artist(['name' => $artistName]);
                            $artist->save();
                            $newArtists++;
                        }
                        if (!$song->artists()->where('artist_id', $artist->id)->exists()) {
                            $song->artists()->attach($artist->id);
                        }
                    }
                    $skipped++;
                    continue;
                }

                // Create new song
                $song = new Song(['title' => $title, 'lyrics' => $lyrics]);
                $song->views = $views;
                $song->save();
                $newSongs++;

                // Link artist
                if ($artistName) {
                    $artist = Artist::where('name', $artistName)->first();
                    if (!$artist) {
                        $artist = new Artist(['name' => $artistName]);
                        $artist->save();
                        $newArtists++;
                    }
                    $song->artists()->attach($artist->id);
                }
            }
            DB::commit();
        } catch (\Exception $e) {
            DB::rollBack();
            throw $e;
        }

        return ['songs' => $newSongs, 'artists' => $newArtists, 'skipped' => $skipped];
    }
}
