<?php

namespace App\Http\Controllers;

use App\Helpers\AiTokenHelper;
use App\Models\HR\Employee;
use App\Models\Rd\AiQuotation;
use App\Models\Tenants\Department;
use App\Models\Tenants\Tenant;
use App\Services\Rd\AiQuotationService;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
use Illuminate\View\View;

class RdController extends Controller
{
    public function __construct(
        private readonly AiQuotationService $quotationService
    ) {}

    /**
     * R&D 대시보드
     */
    public function index(Request $request): View|\Illuminate\Http\Response
    {
        if ($request->header('HX-Request')) {
            return response('', 200)->header('HX-Redirect', route('rd.index'));
        }

        $dashboard = $this->quotationService->getDashboardStats();
        $statuses = AiQuotation::getStatuses();

        return view('rd.index', compact('dashboard', 'statuses'));
    }

    /**
     * 조직도 관리
     */
    public function orgChart(Request $request): View|\Illuminate\Http\Response
    {
        if ($request->header('HX-Request')) {
            return response('', 200)->header('HX-Redirect', route('rd.org-chart'));
        }

        $tenantId = session('selected_tenant_id');

        // 부서 트리 (parent_id=null이 최상위)
        $departments = Department::where('tenant_id', $tenantId)
            ->where('is_active', true)
            ->orderBy('sort_order')
            ->orderBy('name')
            ->get();

        // 전체 직원 (활성 상태)
        $rawEmployees = Employee::withoutGlobalScopes()
            ->where('tenant_id', $tenantId)
            ->where('employee_status', 'active')
            ->with(['user', 'department'])
            ->orderBy('display_name')
            ->get();

        // Blade @json 호환을 위해 미리 배열로 변환
        $employees = $rawEmployees->map(function ($e) {
            return [
                'id' => $e->id,
                'user_id' => $e->user_id,
                'department_id' => $e->department_id,
                'display_name' => $e->display_name ?? $e->user?->name ?? '(이름없음)',
                'position_label' => $e->position_label,
            ];
        })->values();

        // 회사 정보 (조직도 최상단)
        $tenant = Tenant::find($tenantId);
        $companyName = $tenant->company_name ?? 'SAM';
        $ceoName = $tenant->ceo_name ?? '';

        return view('rd.org-chart', compact('departments', 'employees', 'companyName', 'ceoName'));
    }

    /**
     * 조직도 - 직원 부서 배치
     */
    public function orgChartAssign(Request $request): JsonResponse
    {
        $request->validate([
            'employee_id' => 'required|integer',
            'department_id' => 'required|integer',
        ]);

        $tenantId = session('selected_tenant_id');
        $employee = Employee::withoutGlobalScopes()
            ->where('tenant_id', $tenantId)
            ->where('id', $request->employee_id)
            ->first();

        if (! $employee) {
            return response()->json(['success' => false, 'message' => '직원을 찾을 수 없습니다.'], 404);
        }

        $employee->department_id = $request->department_id;
        $employee->save();

        return response()->json(['success' => true]);
    }

    /**
     * 조직도 - 직원 부서 해제 (미배치로 이동)
     */
    public function orgChartUnassign(Request $request): JsonResponse
    {
        $request->validate([
            'employee_id' => 'required|integer',
        ]);

        $tenantId = session('selected_tenant_id');
        $employee = Employee::withoutGlobalScopes()
            ->where('tenant_id', $tenantId)
            ->where('id', $request->employee_id)
            ->first();

        if (! $employee) {
            return response()->json(['success' => false, 'message' => '직원을 찾을 수 없습니다.'], 404);
        }

        $employee->department_id = null;
        $employee->save();

        return response()->json(['success' => true]);
    }

    /**
     * 조직도 - 부서 내 직원 순서/이동 일괄 처리
     */
    public function orgChartReorder(Request $request): JsonResponse
    {
        $request->validate([
            'moves' => 'required|array',
            'moves.*.employee_id' => 'required|integer',
            'moves.*.department_id' => 'nullable|integer',
        ]);

        $tenantId = session('selected_tenant_id');

        foreach ($request->moves as $move) {
            Employee::withoutGlobalScopes()
                ->where('tenant_id', $tenantId)
                ->where('id', $move['employee_id'])
                ->update(['department_id' => $move['department_id']]);
        }

        return response()->json(['success' => true]);
    }

    /**
     * 조직도 - 부서 순서 변경 (드래그 앤 드롭)
     */
    public function orgChartReorderDepts(Request $request): JsonResponse
    {
        $request->validate([
            'orders' => 'required|array',
            'orders.*.id' => 'required|integer',
            'orders.*.parent_id' => 'nullable|integer',
            'orders.*.sort_order' => 'required|integer',
        ]);

        $tenantId = session('selected_tenant_id');

        foreach ($request->orders as $order) {
            Department::where('tenant_id', $tenantId)
                ->where('id', $order['id'])
                ->update([
                    'parent_id' => $order['parent_id'],
                    'sort_order' => $order['sort_order'],
                ]);
        }

        return response()->json(['success' => true]);
    }

    /**
     * 조직도 - 부서 숨기기/표시 토글
     */
    public function orgChartToggleHide(Request $request): JsonResponse
    {
        $request->validate([
            'department_id' => 'required|integer',
            'hidden' => 'required|boolean',
        ]);

        $tenantId = session('selected_tenant_id');
        $dept = Department::where('tenant_id', $tenantId)
            ->where('id', $request->department_id)
            ->first();

        if (! $dept) {
            return response()->json(['success' => false, 'message' => '부서를 찾을 수 없습니다.'], 404);
        }

        $options = $dept->options ?? [];
        $options['orgchart_hidden'] = $request->hidden;
        $dept->options = $options;
        $dept->save();

        return response()->json(['success' => true]);
    }

    /**
     * 중대재해처벌법 실무 점검
     */
    public function safetyAudit(Request $request): View|\Illuminate\Http\Response
    {
        if ($request->header('HX-Request')) {
            return response('', 200)->header('HX-Redirect', route('rd.safety-audit'));
        }

        return view('rd.safety-audit');
    }

    /**
     * AI 견적 목록
     */
    public function quotations(Request $request): View|\Illuminate\Http\Response
    {
        if ($request->header('HX-Request')) {
            return response('', 200)->header('HX-Redirect', route('rd.ai-quotation.index'));
        }

        $statuses = AiQuotation::getStatuses();

        return view('rd.ai-quotation.index', compact('statuses'));
    }

    /**
     * AI 견적 생성 폼
     */
    public function createQuotation(Request $request): View|\Illuminate\Http\Response
    {
        if ($request->header('HX-Request')) {
            return response('', 200)->header('HX-Redirect', route('rd.ai-quotation.create'));
        }

        return view('rd.ai-quotation.create');
    }

    /**
     * AI 견적 문서 (인쇄용 견적서)
     */
    public function documentQuotation(Request $request, int $id): View
    {
        $quotation = $this->quotationService->getById($id);

        if (! $quotation || ! $quotation->isCompleted()) {
            abort(404, '완료된 견적만 문서로 조회할 수 있습니다.');
        }

        $template = $request->query('template', 'classic');
        $allowed = ['classic', 'modern', 'blue', 'dark', 'colorful'];
        if (! in_array($template, $allowed)) {
            $template = 'classic';
        }

        return view('rd.ai-quotation.document', compact('quotation', 'template'));
    }

    /**
     * AI 견적 상세
     */
    public function showQuotation(Request $request, int $id): View|\Illuminate\Http\Response
    {
        if ($request->header('HX-Request')) {
            return response('', 200)->header('HX-Redirect', route('rd.ai-quotation.show', $id));
        }

        $quotation = $this->quotationService->getById($id);

        if (! $quotation) {
            abort(404, 'AI 견적을 찾을 수 없습니다.');
        }

        return view('rd.ai-quotation.show', compact('quotation'));
    }

    /**
     * AI 견적 편집 (제조 모드)
     */
    public function editQuotation(Request $request, int $id): View|\Illuminate\Http\Response
    {
        if ($request->header('HX-Request')) {
            return response('', 200)->header('HX-Redirect', route('rd.ai-quotation.edit', $id));
        }

        $quotation = $this->quotationService->getById($id);

        if (! $quotation) {
            abort(404, 'AI 견적을 찾을 수 없습니다.');
        }

        if (! $quotation->isCompleted()) {
            abort(403, '완료된 견적만 편집할 수 있습니다.');
        }

        return view('rd.ai-quotation.edit', compact('quotation'));
    }

    /**
     * 기획디자인 - 플래닝 캔버스
     */
    public function planningDesign(Request $request): View|\Illuminate\Http\Response
    {
        if ($request->header('HX-Request')) {
            return response('', 200)->header('HX-Redirect', route('rd.planning-design'));
        }

        return view('rd.planning-design.index');
    }

    /**
     * 디자인 인사이트 - UI/UX 연구 도구
     */
    public function designInsight(Request $request): View|\Illuminate\Http\Response
    {
        if ($request->header('HX-Request')) {
            return response('', 200)->header('HX-Redirect', route('rd.design-insight'));
        }

        return view('rd.design-insight.index');
    }

    /**
     * 사운드 로고 생성기
     */
    public function soundLogo(Request $request): View|\Illuminate\Http\Response
    {
        if ($request->header('HX-Request')) {
            return response('', 200)->header('HX-Redirect', route('rd.sound-logo'));
        }

        return view('rd.sound-logo.index');
    }

    /**
     * Lyria RealTime 접속용 API 설정 반환
     */
    public function soundLogoLyriaConfig(): JsonResponse
    {
        $apiKey = config('services.gemini.api_key');

        if (! $apiKey) {
            return response()->json(['success' => false, 'error' => 'API 키가 설정되지 않았습니다.'], 500);
        }

        return response()->json([
            'success' => true,
            'api_key' => $apiKey,
            'ws_url' => 'wss://generativelanguage.googleapis.com/ws/google.ai.generativelanguage.v1alpha.GenerativeService.BidiGenerateMusic',
            'model' => 'models/lyria-realtime-exp',
        ]);
    }

    /**
     * 사운드 로고 AI 생성 (Gemini API)
     */
    public function soundLogoGenerate(Request $request): JsonResponse
    {
        $request->validate([
            'prompt' => 'required|string|max:500',
            'category' => 'nullable|string',
            'duration' => 'nullable|numeric|min:0.3|max:5',
        ]);

        $apiKey = config('services.gemini.api_key');
        $baseUrl = config('services.gemini.base_url', 'https://generativelanguage.googleapis.com/v1beta');
        $model = config('services.gemini.model', 'gemini-2.5-flash');

        if (! $apiKey) {
            return response()->json(['success' => false, 'error' => 'Gemini API 키가 설정되지 않았습니다.'], 500);
        }

        $category = $request->category ?? '기업 시그널';
        $duration = $request->duration ?? 1.5;

        $prompt = <<<PROMPT
당신은 사운드 디자인 전문가입니다. 사용자의 요청에 맞는 사운드 로고(짧은 시그니처 사운드)를 Web Audio API 음표 시퀀스로 설계해주세요.

## 사용자 요청
- 설명: {$request->prompt}
- 카테고리: {$category}
- 목표 길이: {$duration}초

## 사용 가능한 음표
C3, C#3, D3, D#3, E3, F3, F#3, G3, G#3, A3, A#3, B3,
C4, C#4, D4, D#4, E4, F4, F#4, G4, G#4, A4, A#4, B4,
C5, C#5, D5, D#5, E5, F5, F#5, G5, G#5, A5, A#5, B5, C6

## 음표 타입
- note: 단일 음 (note 필드 필수)
- chord: 화음 (chord 배열 필수, 2~4개 음)
- rest: 쉼표 (duration만 필요)

## 신스 타입
- sine: 부드러움 (기업 로고, 알림에 적합)
- triangle: 따뜻함 (성공, 게임에 적합)
- square: 8bit/디지털 (게임, UI에 적합)
- sawtooth: 날카로움 (록, 긴급 알림에 적합)

## 반드시 아래 JSON 형식으로만 응답하세요
{
  "name": "사운드 이름",
  "desc": "사운드 설명 (한줄)",
  "synth": "sine",
  "adsr": { "attack": 10, "decay": 80, "sustain": 0.6, "release": 400 },
  "volume": 0.8,
  "reverb": 0.3,
  "notes": [
    { "type": "note", "note": "C5", "duration": 0.20, "velocity": 0.8 },
    { "type": "rest", "duration": 0.10 },
    { "type": "chord", "chord": ["C4", "E4", "G4"], "duration": 0.50, "velocity": 1.0 }
  ]
}

## 설계 원칙
- 음표의 duration 합계가 목표 길이({$duration}초)에 근접하도록 설계
- velocity: 0.3~1.0 (음의 강약으로 표현력 추가)
- ADSR: attack(1~500ms), decay(10~1000ms), sustain(0~1.0), release(10~3000ms)
- 카테고리 특성에 맞는 synth와 ADSR 선택
- 음악적으로 조화롭고 기억에 남는 멜로디 설계
- 최소 2개, 최대 12개 음표 사용
- name은 10자 이내, desc는 30자 이내로 간결하게 작성
PROMPT;

        try {
            $response = Http::timeout(30)->post(
                "{$baseUrl}/models/{$model}:generateContent?key={$apiKey}",
                [
                    'contents' => [
                        ['parts' => [['text' => $prompt]]],
                    ],
                    'generationConfig' => [
                        'temperature' => 0.7,
                        'maxOutputTokens' => 4096,
                        'responseMimeType' => 'application/json',
                    ],
                ]
            );
        } catch (\Exception $e) {
            Log::error('SoundLogo AI 생성 실패', ['error' => $e->getMessage()]);

            return response()->json(['success' => false, 'error' => 'AI 서버 연결 실패'], 500);
        }

        if (! $response->successful()) {
            Log::error('SoundLogo AI API 오류', ['status' => $response->status(), 'body' => $response->body()]);

            return response()->json(['success' => false, 'error' => 'AI 생성 실패: '.$response->status()], 500);
        }

        $data = $response->json();

        // 토큰 사용량 기록
        AiTokenHelper::saveGeminiUsage($data, $model, '사운드로고-AI생성');

        $text = $data['candidates'][0]['content']['parts'][0]['text'] ?? '';

        // JSON 파싱 (코드블록 제거)
        $text = preg_replace('/^```(?:json)?\s*/m', '', $text);
        $text = preg_replace('/```\s*$/m', '', $text);
        $result = json_decode(trim($text), true);

        if (! $result || ! isset($result['notes'])) {
            Log::warning('SoundLogo AI 응답 파싱 실패', ['text' => substr($text, 0, 500)]);

            return response()->json(['success' => false, 'error' => 'AI 응답을 파싱할 수 없습니다.'], 500);
        }

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

    /**
     * 사운드 로고 TTS 음성 생성 (Gemini TTS API)
     */
    public function soundLogoTts(Request $request): JsonResponse
    {
        $request->validate([
            'text' => 'required|string|max:200',
            'voice_name' => 'nullable|string|max:30',
            'voice_category' => 'nullable|string|in:female,male,child',
            'voice_style' => 'nullable|string|max:100',
            'voice_speed' => 'nullable|integer|min:1|max:5',
        ]);

        $apiKey = config('services.gemini.api_key');
        $baseUrl = config('services.gemini.base_url', 'https://generativelanguage.googleapis.com/v1beta');

        if (! $apiKey) {
            return response()->json(['success' => false, 'error' => 'Gemini API 키가 설정되지 않았습니다.'], 500);
        }

        $voiceName = $request->voice_name ?: 'Kore';
        $voiceCategory = $request->voice_category ?: 'female';
        $voiceStyle = $request->voice_style ?: '';
        $voiceSpeed = $request->voice_speed ?: 3;

        // 속도 지시문 매핑
        $speedDirectives = [
            1 => '아주 천천히 또박또박 말해주세요.',
            2 => '조금 느린 속도로 말해주세요.',
            3 => '',
            4 => '조금 빠른 속도로 말해주세요.',
            5 => '아주 빠른 속도로 말해주세요.',
        ];

        // TTS 프롬프트 구성 — Director's Note 형식
        $ttsText = $request->text;
        $notes = [];

        // 아이 카테고리: 높은 톤으로 어린이처럼 연기하도록 강한 지시문
        if ($voiceCategory === 'child') {
            $notes[] = 'Speak as a young child with a high-pitched, innocent voice';
        }

        if ($voiceStyle) {
            $notes[] = $voiceStyle;
        }

        if (! empty($speedDirectives[$voiceSpeed])) {
            $notes[] = $speedDirectives[$voiceSpeed];
        }

        if (! empty($notes)) {
            $direction = implode('. ', $notes);
            $ttsText = "[{$direction}]\n\n{$ttsText}";
        }

        // 짧은 텍스트는 TTS 모델이 텍스트 생성으로 인식할 수 있으므로 발화 컨텍스트 추가
        if (mb_strlen($ttsText) < 4) {
            $ttsText = "'{$ttsText}' ";
        }

        try {
            $response = Http::timeout(30)->post(
                "{$baseUrl}/models/gemini-2.5-flash-preview-tts:generateContent?key={$apiKey}",
                [
                    'contents' => [
                        ['parts' => [['text' => $ttsText]]],
                    ],
                    'generationConfig' => [
                        'responseModalities' => ['AUDIO'],
                        'speechConfig' => [
                            'voiceConfig' => [
                                'prebuiltVoiceConfig' => [
                                    'voiceName' => $voiceName,
                                ],
                            ],
                        ],
                    ],
                ]
            );
        } catch (\Exception $e) {
            Log::error('SoundLogo TTS 생성 실패', ['error' => $e->getMessage()]);

            return response()->json(['success' => false, 'error' => 'TTS 서버 연결 실패'], 500);
        }

        if (! $response->successful()) {
            $body = $response->json();
            $msg = $body['error']['message'] ?? ('TTS 생성 실패: '.$response->status());
            Log::warning('SoundLogo TTS API 에러', ['status' => $response->status(), 'body' => $msg]);

            return response()->json(['success' => false, 'error' => $msg], $response->status());
        }

        $data = $response->json();

        // 토큰 사용량 기록
        AiTokenHelper::saveGeminiUsage($data, 'gemini-2.5-flash-preview-tts', '사운드로고-TTS');

        $inlineData = $data['candidates'][0]['content']['parts'][0]['inlineData'] ?? null;

        if (! $inlineData || empty($inlineData['data'])) {
            return response()->json(['success' => false, 'error' => '음성 데이터를 받지 못했습니다.'], 500);
        }

        return response()->json([
            'success' => true,
            'audio_data' => $inlineData['data'],
            'mime_type' => $inlineData['mimeType'] ?? 'audio/L16;rate=24000',
        ]);
    }
}
