package de.hackernet.wireguardtv.ui

import android.os.Bundle
import android.view.KeyEvent
import android.widget.Toast
import androidx.fragment.app.FragmentActivity
import androidx.leanback.app.GuidedStepSupportFragment
import androidx.leanback.widget.GuidanceStylist
import androidx.leanback.widget.GuidedAction
import androidx.lifecycle.lifecycleScope
import de.hackernet.wireguardtv.R
import de.hackernet.wireguardtv.data.TunnelRepository
import de.hackernet.wireguardtv.model.InterfaceConfig
import de.hackernet.wireguardtv.model.PeerConfig
import de.hackernet.wireguardtv.model.TunnelConfig
import kotlinx.coroutines.launch
import java.util.UUID

/**
 * Tunnel Editor Activity
 * Nutzt Leanback GuidedStepFragment für D-Pad-freundliche Eingabe
 */
class TunnelEditorActivity : FragmentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val tunnelId = intent.getStringExtra("tunnel_id")
        
        if (savedInstanceState == null) {
            if (tunnelId != null) {
                // Existierenden Tunnel bearbeiten
                GuidedStepSupportFragment.addAsRoot(
                    this,
                    EditTunnelFragment.newInstance(tunnelId),
                    android.R.id.content
                )
            } else {
                // Neuen Tunnel erstellen - Methode wählen
                GuidedStepSupportFragment.addAsRoot(
                    this,
                    AddTunnelMethodFragment(),
                    android.R.id.content
                )
            }
        }
    }
}

/**
 * Fragment zur Auswahl der Hinzufüge-Methode
 */
class AddTunnelMethodFragment : GuidedStepSupportFragment() {

    companion object {
        private const val ACTION_MANUAL = 1L
        private const val ACTION_PASTE_CONFIG = 2L
        private const val ACTION_CANCEL = 4L
    }

    override fun onCreateGuidance(savedInstanceState: Bundle?): GuidanceStylist.Guidance {
        return GuidanceStylist.Guidance(
            "Tunnel hinzufügen",
            "Wähle wie du den WireGuard Tunnel hinzufügen möchtest",
            "WireGuard TV",
            null
        )
    }

    override fun onCreateActions(actions: MutableList<GuidedAction>, savedInstanceState: Bundle?) {
        actions.add(GuidedAction.Builder(requireContext())
            .id(ACTION_PASTE_CONFIG)
            .title("Config einfügen")
            .description("WireGuard .conf Datei-Inhalt einfügen")
            .build())

        actions.add(GuidedAction.Builder(requireContext())
            .id(ACTION_MANUAL)
            .title("Manuell eingeben")
            .description("Alle Felder einzeln ausfüllen")
            .build())

        actions.add(GuidedAction.Builder(requireContext())
            .id(ACTION_CANCEL)
            .title("Abbrechen")
            .build())
    }

    override fun onGuidedActionClicked(action: GuidedAction) {
        when (action.id) {
            ACTION_PASTE_CONFIG -> {
                GuidedStepSupportFragment.add(
                    parentFragmentManager,
                    PasteConfigFragment()
                )
            }
            ACTION_MANUAL -> {
                GuidedStepSupportFragment.add(
                    parentFragmentManager,
                    ManualConfigFragment()
                )
            }
            ACTION_CANCEL -> {
                activity?.finish()
            }
        }
    }
}

/**
 * Fragment zum Einfügen einer .conf Datei
 */
class PasteConfigFragment : GuidedStepSupportFragment() {

    companion object {
        private const val ACTION_NAME = 1L
        private const val ACTION_CONFIG = 2L
        private const val ACTION_SAVE = 3L
        private const val ACTION_CANCEL = 4L
    }

    private var tunnelName = "Neuer Tunnel"
    private var configText = ""

    override fun onCreateGuidance(savedInstanceState: Bundle?): GuidanceStylist.Guidance {
        return GuidanceStylist.Guidance(
            "Config einfügen",
            "Füge den Inhalt deiner WireGuard .conf Datei ein",
            "WireGuard TV",
            null
        )
    }

    override fun onCreateActions(actions: MutableList<GuidedAction>, savedInstanceState: Bundle?) {
        actions.add(GuidedAction.Builder(requireContext())
            .id(ACTION_NAME)
            .title("Tunnel Name")
            .description(tunnelName)
            .descriptionEditable(true)
            .descriptionEditInputType(android.text.InputType.TYPE_CLASS_TEXT)
            .build())

        actions.add(GuidedAction.Builder(requireContext())
            .id(ACTION_CONFIG)
            .title("Config Inhalt")
            .description("Tippen zum Einfügen...")
            .descriptionEditable(true)
            .descriptionEditInputType(
                android.text.InputType.TYPE_CLASS_TEXT or 
                android.text.InputType.TYPE_TEXT_FLAG_MULTI_LINE
            )
            .build())

        actions.add(GuidedAction.Builder(requireContext())
            .id(ACTION_SAVE)
            .title("Speichern")
            .build())

        actions.add(GuidedAction.Builder(requireContext())
            .id(ACTION_CANCEL)
            .title("Abbrechen")
            .build())
    }

    override fun onGuidedActionEdited(action: GuidedAction) {
        when (action.id) {
            ACTION_NAME -> tunnelName = action.description?.toString() ?: tunnelName
            ACTION_CONFIG -> configText = action.description?.toString() ?: ""
        }
    }

    override fun onGuidedActionClicked(action: GuidedAction) {
        when (action.id) {
            ACTION_SAVE -> saveConfig()
            ACTION_CANCEL -> activity?.finish()
        }
    }

    private fun saveConfig() {
        if (configText.isBlank()) {
            Toast.makeText(context, "Config darf nicht leer sein", Toast.LENGTH_SHORT).show()
            return
        }

        lifecycleScope.launch {
            try {
                val repository = TunnelRepository.getInstance(requireContext())
                repository.importFromConf(configText, tunnelName)
                Toast.makeText(context, "Tunnel '$tunnelName' gespeichert", Toast.LENGTH_SHORT).show()
                activity?.finish()
            } catch (e: Exception) {
                Toast.makeText(context, "Fehler: ${e.message}", Toast.LENGTH_LONG).show()
            }
        }
    }
}

/**
 * Fragment für manuelle Konfiguration
 */
class ManualConfigFragment : GuidedStepSupportFragment() {

    companion object {
        private const val ACTION_NAME = 1L
        private const val ACTION_PRIVATE_KEY = 2L
        private const val ACTION_ADDRESS = 3L
        private const val ACTION_DNS = 4L
        private const val ACTION_PEER_PUBLIC_KEY = 10L
        private const val ACTION_PEER_ENDPOINT = 11L
        private const val ACTION_PEER_ALLOWED_IPS = 12L
        private const val ACTION_PEER_KEEPALIVE = 13L
        private const val ACTION_SAVE = 100L
        private const val ACTION_CANCEL = 101L
    }

    private var tunnelName = ""
    private var privateKey = ""
    private var address = ""
    private var dns = ""
    private var peerPublicKey = ""
    private var peerEndpoint = ""
    private var peerAllowedIPs = "0.0.0.0/0, ::/0"
    private var peerKeepalive = "25"

    override fun onCreateGuidance(savedInstanceState: Bundle?): GuidanceStylist.Guidance {
        return GuidanceStylist.Guidance(
            "Tunnel konfigurieren",
            "Gib die WireGuard Konfiguration ein",
            "WireGuard TV",
            null
        )
    }

    override fun onCreateActions(actions: MutableList<GuidedAction>, savedInstanceState: Bundle?) {
        // Interface Settings
        actions.add(GuidedAction.Builder(requireContext())
            .id(ACTION_NAME)
            .title("Tunnel Name")
            .descriptionEditable(true)
            .descriptionEditInputType(android.text.InputType.TYPE_CLASS_TEXT)
            .build())

        actions.add(GuidedAction.Builder(requireContext())
            .id(ACTION_PRIVATE_KEY)
            .title("Private Key")
            .descriptionEditable(true)
            .descriptionEditInputType(android.text.InputType.TYPE_CLASS_TEXT)
            .build())

        actions.add(GuidedAction.Builder(requireContext())
            .id(ACTION_ADDRESS)
            .title("Address")
            .description("z.B. 10.0.0.2/24")
            .descriptionEditable(true)
            .build())

        actions.add(GuidedAction.Builder(requireContext())
            .id(ACTION_DNS)
            .title("DNS (optional)")
            .description("z.B. 1.1.1.1")
            .descriptionEditable(true)
            .build())

        // Peer Settings
        actions.add(GuidedAction.Builder(requireContext())
            .id(ACTION_PEER_PUBLIC_KEY)
            .title("Peer Public Key")
            .descriptionEditable(true)
            .build())

        actions.add(GuidedAction.Builder(requireContext())
            .id(ACTION_PEER_ENDPOINT)
            .title("Peer Endpoint")
            .description("z.B. vpn.example.com:51820")
            .descriptionEditable(true)
            .build())

        actions.add(GuidedAction.Builder(requireContext())
            .id(ACTION_PEER_ALLOWED_IPS)
            .title("Allowed IPs")
            .description(peerAllowedIPs)
            .descriptionEditable(true)
            .build())

        actions.add(GuidedAction.Builder(requireContext())
            .id(ACTION_PEER_KEEPALIVE)
            .title("Persistent Keepalive")
            .description(peerKeepalive)
            .descriptionEditable(true)
            .descriptionEditInputType(android.text.InputType.TYPE_CLASS_NUMBER)
            .build())

        // Actions
        actions.add(GuidedAction.Builder(requireContext())
            .id(ACTION_SAVE)
            .title("Speichern")
            .build())

        actions.add(GuidedAction.Builder(requireContext())
            .id(ACTION_CANCEL)
            .title("Abbrechen")
            .build())
    }

    override fun onGuidedActionEdited(action: GuidedAction) {
        val value = action.description?.toString() ?: ""
        when (action.id) {
            ACTION_NAME -> tunnelName = value
            ACTION_PRIVATE_KEY -> privateKey = value
            ACTION_ADDRESS -> address = value
            ACTION_DNS -> dns = value
            ACTION_PEER_PUBLIC_KEY -> peerPublicKey = value
            ACTION_PEER_ENDPOINT -> peerEndpoint = value
            ACTION_PEER_ALLOWED_IPS -> peerAllowedIPs = value
            ACTION_PEER_KEEPALIVE -> peerKeepalive = value
        }
    }

    override fun onGuidedActionClicked(action: GuidedAction) {
        when (action.id) {
            ACTION_SAVE -> saveConfig()
            ACTION_CANCEL -> activity?.finish()
        }
    }

    private fun saveConfig() {
        // Validierung
        if (tunnelName.isBlank() || privateKey.isBlank() || address.isBlank() || peerPublicKey.isBlank()) {
            Toast.makeText(context, "Bitte alle Pflichtfelder ausfüllen", Toast.LENGTH_SHORT).show()
            return
        }

        val config = TunnelConfig(
            id = UUID.randomUUID().toString(),
            name = tunnelName,
            interface_ = InterfaceConfig(
                privateKey = privateKey,
                addresses = address.split(",").map { it.trim() },
                dns = if (dns.isNotBlank()) dns.split(",").map { it.trim() } else emptyList()
            ),
            peers = listOf(
                PeerConfig(
                    publicKey = peerPublicKey,
                    endpoint = peerEndpoint.ifBlank { null },
                    allowedIPs = peerAllowedIPs.split(",").map { it.trim() },
                    persistentKeepalive = peerKeepalive.toIntOrNull()
                )
            )
        )

        lifecycleScope.launch {
            try {
                val repository = TunnelRepository.getInstance(requireContext())
                repository.addTunnel(config)
                Toast.makeText(context, "Tunnel '$tunnelName' gespeichert", Toast.LENGTH_SHORT).show()
                activity?.finish()
            } catch (e: Exception) {
                Toast.makeText(context, "Fehler: ${e.message}", Toast.LENGTH_LONG).show()
            }
        }
    }
}

/**
 * Fragment zum Bearbeiten eines existierenden Tunnels
 */
class EditTunnelFragment : GuidedStepSupportFragment() {

    companion object {
        private const val ARG_TUNNEL_ID = "tunnel_id"
        
        private const val ACTION_NAME = 1L
        private const val ACTION_CONNECT = 2L
        private const val ACTION_EDIT = 3L
        private const val ACTION_EXPORT = 4L
        private const val ACTION_DELETE = 5L
        private const val ACTION_CANCEL = 6L

        fun newInstance(tunnelId: String): EditTunnelFragment {
            return EditTunnelFragment().apply {
                arguments = Bundle().apply {
                    putString(ARG_TUNNEL_ID, tunnelId)
                }
            }
        }
    }

    private var tunnelConfig: TunnelConfig? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        val tunnelId = arguments?.getString(ARG_TUNNEL_ID) ?: return
        
        lifecycleScope.launch {
            val repository = TunnelRepository.getInstance(requireContext())
            tunnelConfig = repository.getTunnel(tunnelId)
            // Actions aktualisieren
            notifyActionChanged(findActionPositionById(ACTION_NAME))
        }
    }

    override fun onCreateGuidance(savedInstanceState: Bundle?): GuidanceStylist.Guidance {
        return GuidanceStylist.Guidance(
            tunnelConfig?.name ?: "Tunnel bearbeiten",
            "Tunnel verwalten",
            "WireGuard TV",
            null
        )
    }

    override fun onCreateActions(actions: MutableList<GuidedAction>, savedInstanceState: Bundle?) {
        actions.add(GuidedAction.Builder(requireContext())
            .id(ACTION_CONNECT)
            .title("Verbinden")
            .build())

        actions.add(GuidedAction.Builder(requireContext())
            .id(ACTION_EXPORT)
            .title("Config anzeigen")
            .description("Als .conf Text")
            .build())

        actions.add(GuidedAction.Builder(requireContext())
            .id(ACTION_DELETE)
            .title("Löschen")
            .build())

        actions.add(GuidedAction.Builder(requireContext())
            .id(ACTION_CANCEL)
            .title("Zurück")
            .build())
    }

    override fun onGuidedActionClicked(action: GuidedAction) {
        when (action.id) {
            ACTION_CONNECT -> {
                tunnelConfig?.let { config ->
                    (activity as? MainActivity)?.connectTunnel(config.id)
                    activity?.finish()
                }
            }
            ACTION_EXPORT -> {
                tunnelConfig?.let { config ->
                    GuidedStepSupportFragment.add(
                        parentFragmentManager,
                        ExportConfigFragment.newInstance(config.id)
                    )
                }
            }
            ACTION_DELETE -> {
                GuidedStepSupportFragment.add(
                    parentFragmentManager,
                    DeleteConfirmFragment.newInstance(tunnelConfig?.id ?: "", tunnelConfig?.name ?: "")
                )
            }
            ACTION_CANCEL -> {
                activity?.finish()
            }
        }
    }
}

/**
 * Fragment zur Anzeige der exportierten Config
 */
class ExportConfigFragment : GuidedStepSupportFragment() {

    companion object {
        private const val ARG_TUNNEL_ID = "tunnel_id"

        fun newInstance(tunnelId: String): ExportConfigFragment {
            return ExportConfigFragment().apply {
                arguments = Bundle().apply {
                    putString(ARG_TUNNEL_ID, tunnelId)
                }
            }
        }
    }

    private var configText = ""

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        
        val tunnelId = arguments?.getString(ARG_TUNNEL_ID) ?: return
        
        lifecycleScope.launch {
            val repository = TunnelRepository.getInstance(requireContext())
            configText = repository.exportToConf(tunnelId) ?: "Fehler beim Export"
        }
    }

    override fun onCreateGuidance(savedInstanceState: Bundle?): GuidanceStylist.Guidance {
        return GuidanceStylist.Guidance(
            "Config Export",
            configText,
            "WireGuard TV",
            null
        )
    }

    override fun onCreateActions(actions: MutableList<GuidedAction>, savedInstanceState: Bundle?) {
        actions.add(GuidedAction.Builder(requireContext())
            .id(1L)
            .title("Zurück")
            .build())
    }

    override fun onGuidedActionClicked(action: GuidedAction) {
        parentFragmentManager.popBackStack()
    }
}

/**
 * Bestätigungsdialog zum Löschen
 */
class DeleteConfirmFragment : GuidedStepSupportFragment() {

    companion object {
        private const val ARG_TUNNEL_ID = "tunnel_id"
        private const val ARG_TUNNEL_NAME = "tunnel_name"

        fun newInstance(tunnelId: String, tunnelName: String): DeleteConfirmFragment {
            return DeleteConfirmFragment().apply {
                arguments = Bundle().apply {
                    putString(ARG_TUNNEL_ID, tunnelId)
                    putString(ARG_TUNNEL_NAME, tunnelName)
                }
            }
        }
    }

    override fun onCreateGuidance(savedInstanceState: Bundle?): GuidanceStylist.Guidance {
        val name = arguments?.getString(ARG_TUNNEL_NAME) ?: ""
        return GuidanceStylist.Guidance(
            "Tunnel löschen?",
            "Möchtest du den Tunnel '$name' wirklich löschen?",
            "WireGuard TV",
            null
        )
    }

    override fun onCreateActions(actions: MutableList<GuidedAction>, savedInstanceState: Bundle?) {
        actions.add(GuidedAction.Builder(requireContext())
            .id(1L)
            .title("Ja, löschen")
            .build())

        actions.add(GuidedAction.Builder(requireContext())
            .id(2L)
            .title("Abbrechen")
            .build())
    }

    override fun onGuidedActionClicked(action: GuidedAction) {
        if (action.id == 1L) {
            val tunnelId = arguments?.getString(ARG_TUNNEL_ID) ?: return
            
            lifecycleScope.launch {
                val repository = TunnelRepository.getInstance(requireContext())
                repository.deleteTunnel(tunnelId)
                Toast.makeText(context, "Tunnel gelöscht", Toast.LENGTH_SHORT).show()
                activity?.finish()
            }
        } else {
            parentFragmentManager.popBackStack()
        }
    }
}
