import { useState, useCallback, useEffect, useRef } from 'react'
import { Button, Dialog, Notification, toast } from '@/components/ui'
import Container from '@/components/shared/Container'
import { getDataSources } from '@/services/data-source.service'
import type { DataSourceDto } from '@/proxy/data-source'
import type { SqlQueryExecutionResultDto } from '@/proxy/sql-query-manager/models'
import { sqlObjectManagerService } from '@/services/sql-query-manager.service'
import { FaDatabase, FaPlay, FaFileAlt } from 'react-icons/fa'
import { FaCheckCircle } from 'react-icons/fa'
import { useLocalization } from '@/utils/hooks/useLocalization'
import SqlObjectExplorer from './SqlObjectExplorer'
import SqlEditor, { SqlEditorRef } from './SqlEditor'
import SqlResultsGrid from './SqlResultsGrid'
import SqlTableDesignerDialog from './SqlTableDesignerDialog'
import { Splitter } from '@/components/codeLayout/Splitter'
import { Helmet } from 'react-helmet'
import { useStoreState } from '@/store/store'
import { APP_NAME } from '@/constants/app.constant'

interface SqlManagerState {
  dataSources: DataSourceDto[]
  selectedDataSource: string | null
  editorContent: string
  isExecuting: boolean
  executionResult: SqlQueryExecutionResultDto | null
  showProperties: boolean
  isDirty: boolean
  tableColumns: any | null
  refreshTrigger: number
}

const SqlQueryManager = () => {
  const { translate } = useLocalization()
  const editorRef = useRef<SqlEditorRef>(null)
  const tenantName = useStoreState((state) => state.locale.currentTenantName)

  const [state, setState] = useState<SqlManagerState>({
    dataSources: [],
    selectedDataSource: tenantName ?? null,
    editorContent: '',
    isExecuting: false,
    refreshTrigger: 0,
    executionResult: null,
    showProperties: false,
    isDirty: false,
    tableColumns: null,
  })

  const [showTemplateConfirmDialog, setShowTemplateConfirmDialog] = useState(false)
  const [pendingTemplate, setPendingTemplate] = useState<{ content: string; type: string } | null>(
    null,
  )
  const [showTableDesignerDialog, setShowTableDesignerDialog] = useState(false)
  const [designTableData, setDesignTableData] = useState<{
    schemaName: string
    tableName: string
  } | null>(null)

  useEffect(() => {
    loadDataSources()
  }, [])

  const loadDataSources = async () => {
    try {
      const response = await getDataSources()
      const items = response.data.items || []
      if (items.length > 0) {
        setState((prev) => ({
          ...prev,
          dataSources: items,
          selectedDataSource: items[0].code ?? null,
        }))
      }
    } catch (error) {
      toast.push(
        <Notification type="danger" title={translate('::App.Platform.Error')}>
          {translate('::App.Platform.FailedtoloadDatasources')}
        </Notification>,
        { placement: 'top-center' },
      )
    }
  }

  const handleDataSourceChange = useCallback((dataSource: DataSourceDto) => {
    setState((prev) => ({
      ...prev,
      selectedDataSource: dataSource.code ?? null,
      editorContent: '',
      executionResult: null,
      isDirty: false,
    }))
  }, [])

  const handleNewTable = useCallback(() => {
    setDesignTableData(null)
    setShowTableDesignerDialog(true)
  }, [])

  const handleDesignTable = useCallback((schemaName: string, tableName: string) => {
    setDesignTableData({ schemaName, tableName })
    setShowTableDesignerDialog(true)
  }, [])

  const handleEditorChange = useCallback((value: string | undefined) => {
    setState((prev) => ({
      ...prev,
      editorContent: value || '',
      isDirty: true,
    }))
  }, [])

  const getTemplateContent = (templateType: string): string => {
    const templates: Record<string, string> = {
      select: `-- Basic SELECT query
SELECT 
    Column1,
    Column2,
    Column3
FROM 
    TableName
WHERE 
    -- Add your conditions
    Column1 = 'value'
    AND IsActive = 1
ORDER BY 
    Column1 ASC;`,

      insert: `-- Basic INSERT query
INSERT INTO TableName (Column1, Column2, Column3)
VALUES 
    ('Value1', 'Value2', 'Value3');`,

      update: `-- Basic UPDATE query
UPDATE TableName
SET 
    Column1 = 'NewValue1',
    Column2 = 'NewValue2'
WHERE 
    -- Add your conditions
    Id = 1;`,

      delete: `-- Basic DELETE query
DELETE FROM TableName
WHERE 
    -- Add your conditions
    Id = 1;`,

      'create-procedure': `-- Create Stored Procedure
CREATE PROCEDURE [dbo].[ProcedureName]
    @Parameter1 INT,
    @Parameter2 NVARCHAR(100)
AS
BEGIN
    SET NOCOUNT ON;
    
    -- Add your logic here
    SELECT 
        Column1,
        Column2
    FROM 
        TableName
    WHERE 
        Column1 = @Parameter1
        AND Column2 = @Parameter2;
END
GO`,

      'create-view': `-- Create View
CREATE VIEW [dbo].[ViewName]
AS
SELECT 
    t1.Column1,
    t1.Column2,
    t2.Column3
FROM 
    TableName1 t1
    INNER JOIN TableName2 t2 ON t1.Id = t2.TableName1Id
WHERE 
    t1.IsActive = 1;
GO`,

      'create-scalar-function': `-- Create Scalar Function
CREATE FUNCTION [dbo].[ScalarFunctionName]
(
    @Parameter1 INT,
    @Parameter2 NVARCHAR(100)
)
RETURNS NVARCHAR(200)
AS
BEGIN
    DECLARE @Result NVARCHAR(200);
    
    -- Add your logic here
    SELECT @Result = Column1 + ' ' + @Parameter2
    FROM TableName
    WHERE Id = @Parameter1;
    
    RETURN @Result;
END
GO`,

      'create-table-function': `-- Create Table-Valued Function
CREATE FUNCTION [dbo].[TableFunctionName]
(
    @Parameter1 INT,
    @Parameter2 NVARCHAR(100)
)
RETURNS TABLE
AS
RETURN
(
    SELECT 
        t.Column1,
        t.Column2,
        t.Column3,
        t.Column4
    FROM 
        TableName t
    WHERE 
        t.Id = @Parameter1
        AND t.Column2 LIKE '%' + @Parameter2 + '%'
        AND t.IsActive = 1
)
GO`,
    }

    return templates[templateType] || templates['select']
  }

  const applyTemplate = useCallback((templateContent: string) => {
    setState((prev) => ({
      ...prev,
      editorContent: templateContent,
      executionResult: null,
      isDirty: false,
    }))
  }, [])

  const handleUseTemplateFromDialog = useCallback(
    (templateContent: string, templateType: string) => {
      // Check if editor has content
      const hasUserContent = state.editorContent?.trim() && state.isDirty

      if (hasUserContent) {
        // Ask for confirmation
        setPendingTemplate({ content: templateContent, type: templateType })
        setShowTemplateConfirmDialog(true)
      } else {
        // Apply template directly
        applyTemplate(templateContent)
      }
    },
    [state.editorContent, state.isDirty, applyTemplate],
  )

  const handleTemplateSelect = useCallback(
    (template: string, templateType: string) => {
      // If template is already provided (e.g., from table click), use it
      const templateContent = template || getTemplateContent(templateType)

      // Check if editor has content and it's not from a previous template
      const hasUserContent = state.editorContent?.trim() && state.isDirty

      if (hasUserContent) {
        // Ask for confirmation
        setPendingTemplate({ content: templateContent, type: templateType })
        setShowTemplateConfirmDialog(true)
      } else {
        // Apply template directly
        applyTemplate(templateContent)
      }
    },
    [translate, state.editorContent, state.isDirty, applyTemplate],
  )

  const handleConfirmTemplateReplace = useCallback(() => {
    if (pendingTemplate) {
      applyTemplate(pendingTemplate.content)
    }
    setShowTemplateConfirmDialog(false)
    setPendingTemplate(null)
  }, [pendingTemplate, applyTemplate])

  const handleCancelTemplateReplace = useCallback(() => {
    setShowTemplateConfirmDialog(false)
    setPendingTemplate(null)
  }, [])

  const handleNewQuery = useCallback(() => {
    setState((prev) => ({
      ...prev,
      editorContent: '',
      executionResult: null,
      tableColumns: null,
      isDirty: false,
    }))
  }, [])

  const handleExecute = async () => {
    if (!state.selectedDataSource) {
      toast.push(
        <Notification type="warning" title={translate('::App.Platform.Warning')}>
          {translate('::App.Platform.PleaseSelectDataSource')}
        </Notification>,
        { placement: 'top-center' },
      )
      return
    }

    // Seçili text varsa onu, yoksa tüm editor içeriğini kullan
    const selectedText = editorRef.current?.getSelectedText() || ''
    const queryToExecute = selectedText.trim() || state.editorContent?.trim() || ''

    if (!queryToExecute) {
      toast.push(
        <Notification type="warning" title={translate('::App.Platform.Warning')}>
          {translate('::App.Platform.PleaseEnterQuery')}
        </Notification>,
        { placement: 'top-center' },
      )
      return
    }

    // Seçili metni koru
    const savedSelection = editorRef.current?.preserveSelection()

    setState((prev) => ({ ...prev, isExecuting: true, executionResult: null, tableColumns: null }))

    try {
      const result = await sqlObjectManagerService.executeQuery({
        queryText: queryToExecute,
        dataSourceCode: state.selectedDataSource || '',
      })

      setState((prev) => ({
        ...prev,
        executionResult: result.data,
        isExecuting: false,
        tableColumns: null,
      }))

      // Seçili metni geri yükle
      setTimeout(() => {
        if (savedSelection) {
          editorRef.current?.restoreSelection(savedSelection)
        }
      }, 100)
    } catch (error: any) {
      setState((prev) => ({ ...prev, isExecuting: false }))

      // Hata durumunda da seçili metni geri yükle
      setTimeout(() => {
        if (savedSelection) {
          editorRef.current?.restoreSelection(savedSelection)
        }
      }, 100)

      toast.push(
        <Notification type="danger" title={translate('::App.Platform.Error')}>
          {error.response?.data?.error?.message || translate('::App.Platform.FailedToExecuteQuery')}
        </Notification>,
        { placement: 'top-center' },
      )
    }
  }

  const handleViewDefinition = async (schemaName: string, objectName: string) => {
    if (!state.selectedDataSource) return
    try {
      const result = await sqlObjectManagerService.getNativeObjectDefinition(
        state.selectedDataSource,
        schemaName,
        objectName,
      )
      if (result.data) {
        const definition = result.data.replace(/\bCREATE\b/i, 'ALTER')
        setState((prev) => ({
          ...prev,
          editorContent: definition,
          executionResult: null,
          tableColumns: null,
          isDirty: false,
        }))
      }
    } catch (error: any) {
      toast.push(
        <Notification type="danger" title={translate('::App.Platform.Error')}>
          {error.response?.data?.error?.message ||
            translate('::App.Platform.FailedToLoadDefinition')}
        </Notification>,
        { placement: 'top-center' },
      )
    }
  }

  return (
    <Container className="flex flex-col overflow-hidden" style={{ height: 'calc(100vh - 130px)' }}>
      <Helmet
        titleTemplate={`%s | ${APP_NAME}`}
        title={translate('::' + 'App.SqlQueryManager')}
        defaultTitle={APP_NAME}
      ></Helmet>

      <div className="flex flex-col flex-1 min-h-0 p-1">
        {/* Toolbar */}
        <div className="flex-shrink-0 shadow-sm mb-4">
          <div className="flex items-center justify-between px-1 py-1">
            <div className="flex items-center gap-3">
              <FaDatabase className="text-lg text-blue-500" />
              <span className="text-sm font-medium text-gray-600 dark:text-gray-400">
                {translate('::App.Platform.DataSource')}:
              </span>
              <select
                className="border border-gray-300 rounded px-1 py-1"
                disabled={state.selectedDataSource?.length === 0}
                value={state.selectedDataSource || ''}
                onChange={(e) => {
                  const ds = state.dataSources.find((d) => d.code === e.target.value)
                  if (ds) handleDataSourceChange(ds)
                }}
              >
                {state.dataSources.map((ds) => (
                  <option key={ds.code} value={ds.code}>
                    {ds.code}
                  </option>
                ))}
              </select>
            </div>

            <div className="flex items-center gap-3">
              <Button
                size="sm"
                variant="default"
                icon={<FaFileAlt />}
                onClick={handleNewQuery}
                className="shadow-sm"
              >
                {translate('::App.Platform.NewQuery') || 'New Query'}
              </Button>
              <Button
                size="sm"
                variant="solid"
                color="blue-600"
                icon={<FaPlay />}
                onClick={handleExecute}
                loading={state.isExecuting}
                disabled={!state.selectedDataSource}
                className="shadow-sm"
              >
                {translate('::App.Platform.Execute')}
                <span className="ml-1 text-xs opacity-75">(F5)</span>
              </Button>
            </div>
          </div>
        </div>

        {/* Main Content Area */}
        <div className="flex-1 flex min-h-0">
          {/* Left Panel - Object Explorer */}
          <div className="w-1/3 flex-shrink-0 flex flex-col min-h-0 mr-4 bg-white dark:bg-gray-800 rounded-lg border border-gray-200 dark:border-gray-600 shadow">
            <div className="border-b px-4 py-2 bg-gray-50 dark:bg-gray-800 flex-shrink-0 rounded-t-lg">
              <h6 className="font-semibold text-sm">
                {translate('::App.Platform.ObjectExplorer')}
              </h6>
            </div>
            <div className="flex-1 min-h-0 flex flex-col overflow-hidden">
              <SqlObjectExplorer
                dataSource={state.selectedDataSource}
                onTemplateSelect={handleTemplateSelect}
                onViewDefinition={handleViewDefinition}
                refreshTrigger={state.refreshTrigger}
                onNewTable={handleNewTable}
                onDesignTable={handleDesignTable}
              />
            </div>
          </div>

          {/* Center Panel - Editor and Results */}
          <div className="flex-1 flex flex-col min-h-0 mr-4">
            {state.executionResult || state.tableColumns ? (
              <Splitter direction="vertical" initialSize={250} minSize={150} maxSize={1200}>
                <div className="border rounded-lg shadow-sm bg-white dark:bg-gray-800 flex flex-col h-full">
                  <div className="border-b px-4 py-2 bg-gray-50 dark:bg-gray-800 flex-shrink-0">
                    <h6 className="font-semibold text-sm">
                      {translate('::App.Platform.QueryEditor')}
                    </h6>
                  </div>
                  <div className="flex-1 min-h-0 overflow-hidden">
                    <SqlEditor
                      ref={editorRef}
                      value={state.editorContent}
                      onChange={handleEditorChange}
                      onExecute={handleExecute}
                      readOnly={state.isExecuting}
                    />
                  </div>
                </div>
                <div className="border rounded-lg shadow-sm bg-white dark:bg-gray-800 flex flex-col h-full">
                  <div className="border-b px-4 py-2 bg-gray-50 dark:bg-gray-800 flex-shrink-0 flex items-center justify-between">
                    <div className="flex items-center gap-2">
                      <FaCheckCircle className="text-green-500" />
                      <span className="text-sm text-green-700 dark:text-green-400">
                        {state.executionResult?.message ||
                          state.tableColumns?.message ||
                          translate('::App.Platform.QueryExecutedSuccessfully')}
                      </span>
                    </div>
                    <div className="flex items-center gap-4">
                      <div className="flex items-center gap-4 text-sm text-gray-600 dark:text-gray-400">
                        <span>
                          {translate('::App.Platform.Rows')}:{' '}
                          <strong>
                            {state.executionResult?.rowsAffected ||
                              state.executionResult?.data?.length ||
                              state.tableColumns?.rowsAffected ||
                              0}
                          </strong>
                        </span>
                        {state.executionResult && (
                          <span>
                            {translate('::App.Platform.Time')}:{' '}
                            <strong>{state.executionResult.executionTimeMs}ms</strong>
                          </span>
                        )}
                      </div>
                    </div>
                  </div>
                  <div className="flex-1 overflow-hidden p-2">
                    <SqlResultsGrid result={(state.executionResult || state.tableColumns)!} />
                  </div>
                </div>
              </Splitter>
            ) : (
              <div className="flex-1 border rounded-lg shadow-sm bg-white dark:bg-gray-800 flex flex-col overflow-hidden">
                <div className="border-b px-4 py-2 bg-gray-50 dark:bg-gray-800 flex-shrink-0">
                  <h6 className="font-semibold text-sm">
                    {translate('::App.Platform.QueryEditor')}
                  </h6>
                </div>
                <div className="flex-1 min-h-0">
                  <SqlEditor
                    ref={editorRef}
                    value={state.editorContent}
                    onChange={handleEditorChange}
                    onExecute={handleExecute}
                    readOnly={state.isExecuting}
                  />
                </div>
              </div>
            )}
          </div>
        </div>
      </div>

      {/* Template Confirmation Dialog */}
      <Dialog
        isOpen={showTemplateConfirmDialog}
        onClose={handleCancelTemplateReplace}
        onRequestClose={handleCancelTemplateReplace}
      >
        <h5 className="mb-4">{translate('::App.Platform.ConfirmTemplateReplace')}</h5>
        <p className="mb-6 text-gray-600 dark:text-gray-400">
          {translate('::App.Platform.TemplateReplaceWarning')}
        </p>
        <div className="flex justify-end gap-2">
          <Button variant="plain" onClick={handleCancelTemplateReplace}>
            {translate('::Cancel')}
          </Button>
          <Button variant="solid" onClick={handleConfirmTemplateReplace}>
            {translate('::App.Platform.Replace')}
          </Button>
        </div>
      </Dialog>

      {/* Table Designer Dialog */}
      <SqlTableDesignerDialog
        isOpen={showTableDesignerDialog}
        onClose={() => {
          setShowTableDesignerDialog(false)
          setDesignTableData(null)
        }}
        dataSource={state.selectedDataSource ?? ''}
        initialTableData={designTableData}
        onDeployed={() => {
          setState((prev) => ({ ...prev, refreshTrigger: prev.refreshTrigger + 1 }))
        }}
      />
    </Container>
  )
}

export default SqlQueryManager
