# frozen_string_literal: true

# 网元相关路由
module DeviceRoutes
  def self.registered(app)
    # 设备管理页面 (Vue)
    app.get '/devices-vue' do
      @active_page = 'devices'
      erb :devices, layout: true
    end

    # 获取所有设备 API
    app.get '/api/devices' do
      content_type :json
      devices = LocalDevice.order(Sequel.desc(:created_at)).all
      devices.map do |device|
        {
          id: device.id,
          name: device.name,
          device_model: device.device_model,
          ip_address: device.ip_address,
          port: device.port,
          connection_type: device.connection_type,
          username: device.username,
          has_password: !device.encrypted_password.nil? && !device.encrypted_password.empty?,
          has_enable_password: !device.encrypted_enable_password.nil? && !device.encrypted_enable_password.empty?,
          has_root_password: !device.encrypted_root_password.nil? && !device.encrypted_root_password.empty?,
          enable_command: device.enable_command,
          description: device.description,
          active: device.active,
          created_at: device.created_at,
          updated_at: device.updated_at
        }
      end.to_json
    end

    # 同步脚本 API
    app.post '/api/device-scripts/sync' do
      content_type :json
      begin
        cloud_client = CloudClient.instance
        last_sync_setting = SystemSetting.find_or_create(key: 'last_script_sync_time')
        since = last_sync_setting.value

        cloud_scripts = cloud_client.get_scripts_for_sync(since: since)

        created_count = 0
        updated_count = 0
        failed_count = 0

        cloud_scripts.each do |cloud_script|
          begin
            result = CachedScript.create_or_update_from_cloud(cloud_script)
            if result.new?
              created_count += 1
            else
              updated_count += 1
            end
          rescue StandardError => e
            LogService.error("同步脚本失败 #{cloud_script['id']}: #{e.message}")
            failed_count += 1
          end
        end

        new_sync_time = Time.now.iso8601
        last_sync_setting.update(value: new_sync_time)

        {
          success: true,
          synced: created_count + updated_count,
          created: created_count,
          updated: updated_count,
          failed: failed_count
        }.to_json
      rescue StandardError => e
        LogService.error("同步脚本失败: #{e.message}")
        halt 500, { success: false, error: "同步失败: #{e.message}" }.to_json
      end
    end

    # 获取脚本列表 API
    app.get '/api/device-scripts/list' do
      content_type :json
      begin
        scripts = CachedScript.order(Sequel.desc(:updated_at)).all
        scripts.map(&:to_api_hash).to_json
      rescue StandardError => e
        LogService.error("获取脚本列表失败: #{e.message}")
        status 500
        { success: false, error: e.message }.to_json
      end
    end

    # 创建设备任务并立即执行
    app.post '/api/device-scripts/execute' do
      content_type :json
      begin
        params_json = JSON.parse(request.body.read)
        device_ids = params_json['device_ids'] || []
        script_ids = params_json['script_ids'] || []

        if device_ids.empty?
          halt 400, { success: false, error: '请选择至少一个设备' }.to_json
        end

        if script_ids.empty?
          halt 400, { success: false, error: '请选择至少一个脚本' }.to_json
        end

        devices = device_ids.map { |id| LocalDevice[id] }.compact
        scripts = script_ids.map { |id| CachedScript[id] }.compact

        if devices.empty?
          halt 400, { success: false, error: '没有找到有效的设备' }.to_json
        end

        if scripts.empty?
          halt 400, { success: false, error: '没有找到有效的脚本' }.to_json
        end

        script_info_list = scripts.map do |s|
          {
            'id' => s.id,
            'name' => s.name,
            'description' => s.description,
            'code' => s.code
          }
        end

        device_info_list = devices.map do |d|
          {
            'id' => d.id,
            'name' => d.name,
            'device_model' => d.device_model,
            'device_ip' => d.ip_address
          }
        end

        task_definition = {
          task_json: {
            'default' => {
              'devs' => device_info_list,
              'scripts' => script_info_list
            }
          },
          execution_mode: 'local'
        }

        task = LocalTask.create_from_cloud_definition({
          name: "设备脚本任务 #{Time.now.strftime('%Y%m%d %H:%M')}",
          description: "执行 #{scripts.size} 个脚本在 #{devices.size} 个设备上",
          definition: task_definition
        })

        execution = task.create_new_execution!
        execution.start!

        coordinator = TaskExecutionCoordinator.instance
        coordinator.submit_task(task, execution)

        {
          success: true,
          task_id: task.id,
          execution_id: execution.id,
          message: "任务已创建并开始执行"
        }.to_json
      rescue JSON::ParserError => e
        halt 400, { success: false, error: '无效的JSON格式' }.to_json
      rescue StandardError => e
        LogService.error("创建设备任务失败: #{e.message}")
        halt 500, { success: false, error: "创建任务失败: #{e.message}" }.to_json
      end
    end

    # 获取单个设备 API
    app.get '/api/devices/:id' do
      content_type :json
      device = LocalDevice[params[:id]]
      halt 404, { error: '设备不存在' }.to_json unless device
      {
        id: device.id,
        name: device.name,
        device_model: device.device_model,
        ip_address: device.ip_address,
        port: device.port,
        connection_type: device.connection_type,
        username: device.username,
        has_password: !device.encrypted_password.nil? && !device.encrypted_password.empty?,
        has_enable_password: !device.encrypted_enable_password.nil? && !device.encrypted_enable_password.empty?,
        has_root_password: !device.encrypted_root_password.nil? && !device.encrypted_root_password.empty?,
        enable_command: device.enable_command,
        description: device.description,
        active: device.active
      }.to_json
    end

    # 添加设备 API
    app.post '/api/devices' do
      content_type :json
      begin
        device_params = JSON.parse(request.body.read)
        device = LocalDevice.new(
          name: device_params['name'],
          device_model: device_params['device_model'],
          ip_address: device_params['ip_address'],
          port: device_params['port'] || (device_params['connection_type'] == 'ssh' ? 22 : 23),
          connection_type: device_params['connection_type'],
          username: device_params['username'],
          enable_command: device_params['enable_command'],
          description: device_params['description'],
          active: true
        )
        # 只在密码不为空时设置
        device.password = device_params['password'] if device_params['password'] && !device_params['password'].empty?
        device.enable_password = device_params['enable_password'] if device_params['enable_password'] && !device_params['enable_password'].empty?
        device.root_password = device_params['root_password'] if device_params['root_password'] && !device_params['root_password'].empty?
        
        if device.save
          { success: true, device: device }.to_json
        else
          halt 400, { success: false, errors: device.errors }.to_json
        end
      rescue JSON::ParserError => e
        halt 400, { success: false, error: '无效的JSON格式' }.to_json
      rescue StandardError => e
        LogService.error("添加设备失败: #{e.message}")
        halt 500, { success: false, error: '服务器错误' }.to_json
      end
    end

    # 更新设备 API
    app.put '/api/devices/:id' do
      content_type :json
      begin
        device = LocalDevice[params[:id]]
        halt 404, { success: false, error: '设备不存在' }.to_json unless device
        
        device_params = JSON.parse(request.body.read)
        device.name = device_params['name'] if device_params.key?('name')
        device.device_model = device_params['device_model'] if device_params.key?('device_model')
        device.ip_address = device_params['ip_address'] if device_params.key?('ip_address')
        device.port = device_params['port'] if device_params.key?('port')
        device.connection_type = device_params['connection_type'] if device_params.key?('connection_type')
        device.username = device_params['username'] if device_params.key?('username')
        device.enable_command = device_params['enable_command'] if device_params.key?('enable_command')
        device.description = device_params['description'] if device_params.key?('description')
        device.active = device_params['active'] if device_params.key?('active')
        
        # 只在密码不为空时更新
        device.password = device_params['password'] if device_params['password'] && !device_params['password'].empty?
        device.enable_password = device_params['enable_password'] if device_params['enable_password'] && !device_params['enable_password'].empty?
        device.root_password = device_params['root_password'] if device_params['root_password'] && !device_params['root_password'].empty?
        
        if device.save
          { success: true, device: device }.to_json
        else
          halt 400, { success: false, errors: device.errors }.to_json
        end
      rescue JSON::ParserError => e
        halt 400, { success: false, error: '无效的JSON格式' }.to_json
      rescue StandardError => e
        LogService.error("更新设备失败: #{e.message}")
        halt 500, { success: false, error: '服务器错误' }.to_json
      end
    end

    # 删除设备 API
    app.delete '/api/devices/:id' do
      content_type :json
      begin
        device = LocalDevice[params[:id]]
        halt 404, { success: false, error: '设备不存在' }.to_json unless device

        device.destroy
        { success: true }.to_json
      rescue StandardError => e
        LogService.error("删除设备失败: #{e.message}")
        halt 500, { success: false, error: '服务器错误' }.to_json
      end
    end

    # 同步设备到云端 API
    app.post '/api/devices/sync' do
      content_type :json
      begin
        cloud_client = CloudClient.instance
        LogService.info("手动同步设备到云端")

        sync_result = cloud_client.sync_devices

        if sync_result[:success]
          {
            success: true,
            message: "同步完成",
            synced: sync_result[:synced],
            errors: sync_result[:errors]
          }.to_json
        else
          halt 500, { success: false, error: sync_result[:error] }.to_json
        end
      rescue StandardError => e
        LogService.error("同步设备失败: #{e.message}")
        halt 500, { success: false, error: "同步失败: #{e.message}" }.to_json
      end
    end

    # 设备连通性测试 API
    app.post '/api/devices/:id/test_connection' do
      content_type :json
      begin
        device = LocalDevice[params[:id]]
        halt 404, { success: false, error: '设备不存在' }.to_json unless device

        timeout_seconds = (params[:timeout] || 600).to_i
        result = TelnetDevice.test_conn(device, timeout_seconds)

        # 根据 status 和 message 分析错误类型
        error_type = case result[:status]
          when 'online' then 'connection_online'
          when 'timeout' then 'connection_timeout'
          when 'refused' then 'connection_refused'
          when 'unreachable' then 'connection_unreachable'
          when 'error'
            if result[:message] =~ /登录失败|login incorrect|authentication failed/i
              'login_failed'
            elsif result[:message] =~ /需要特权密码但未提供/i
              'enable_password_required'
            else
              'connection_error'
            end
          end

        LogService.info("设备 #{device.name} 连通性测试完成: #{result[:status]}")

        {
          success: true,
          status: result[:status],
          protocol: result[:protocol],
          message: result[:message],
          error_type: error_type,
          login_steps: result[:login_steps]
        }.to_json
      rescue StandardError => e
        LogService.error("设备连通性测试失败: #{e.message}")
        halt 500, { success: false, error: "测试失败: #{e.message}" }.to_json
      end
    end

    # 保留原有路由以兼容旧代码
    app.get '/devices/new' do
      redirect '/devices-vue'
    end

    app.post '/devices' do
      redirect '/devices-vue'
    end

    app.get '/devices/import' do
      redirect '/devices-vue'
    end

    app.get '/devices/:id/edit' do
      redirect '/devices-vue'
    end
  end
end
