-- CREATE FUNCTION public.check_database_integrity
CREATE OR REPLACE FUNCTION public.check_database_integrity()
RETURNS jsonb
SECURITY DEFINER
AS $$
DECLARE
  profiles_exist boolean;
  end_customers_exist boolean;
  pos_modules_exist boolean;
  licenses_exist boolean;
  
  profiles_count bigint := 0;
  end_customers_count bigint := 0;
  pos_modules_count bigint := 0;
  licenses_count bigint := 0;
  
  fk_errors_count bigint := 0;
  result jsonb;
BEGIN
  -- Check table existence
  SELECT EXISTS (SELECT 1 FROM pg_tables WHERE schemaname = 'public' AND tablename = 'profiles') INTO profiles_exist;
  SELECT EXISTS (SELECT 1 FROM pg_tables WHERE schemaname = 'public' AND tablename = 'end_customers') INTO end_customers_exist;
  SELECT EXISTS (SELECT 1 FROM pg_tables WHERE schemaname = 'public' AND tablename = 'pos_modules') INTO pos_modules_exist;
  SELECT EXISTS (SELECT 1 FROM pg_tables WHERE schemaname = 'public' AND tablename = 'licenses') INTO licenses_exist;

  -- Count rows if table exists
  IF profiles_exist THEN
    EXECUTE 'SELECT count(*) FROM public.profiles' INTO profiles_count;
  END IF;
  
  IF end_customers_exist THEN
    EXECUTE 'SELECT count(*) FROM public.end_customers' INTO end_customers_count;
  END IF;
  
  IF pos_modules_exist THEN
    EXECUTE 'SELECT count(*) FROM public.pos_modules' INTO pos_modules_count;
  END IF;
  
  IF licenses_exist THEN
    EXECUTE 'SELECT count(*) FROM public.licenses' INTO licenses_count;
  END IF;

  -- Count foreign key errors (orphaned licenses)
  IF licenses_exist AND end_customers_exist THEN
    EXECUTE '
      SELECT count(*)
      FROM public.licenses l
      LEFT JOIN public.end_customers c ON l.end_customer_id = c.id
      WHERE c.id IS NULL AND l.end_customer_id IS NOT NULL
    ' INTO fk_errors_count;
  END IF;

  -- Build JSON result
  result := jsonb_build_object(
    'tables', jsonb_build_object(
      'profiles', jsonb_build_object('exists', profiles_exist, 'count', profiles_count),
      'end_customers', jsonb_build_object('exists', end_customers_exist, 'count', end_customers_count),
      'pos_modules', jsonb_build_object('exists', pos_modules_exist, 'count', pos_modules_count),
      'licenses', jsonb_build_object('exists', licenses_exist, 'count', licenses_count)
    ),
    'errors', jsonb_build_object(
      'foreign_keys', fk_errors_count
    )
  );

  RETURN result;
END;
$$ LANGUAGE plpgsql;

-- CREATE FUNCTION public.repair_database_schema
CREATE OR REPLACE FUNCTION public.repair_database_schema()
RETURNS jsonb
SECURITY DEFINER
AS $$
DECLARE
  repaired_tables text[] := '{}';
  result jsonb;
BEGIN
  -- 1. profiles table (should exist, but check just in case)
  IF NOT EXISTS (SELECT 1 FROM pg_tables WHERE schemaname = 'public' AND tablename = 'profiles') THEN
    CREATE TABLE public.profiles (
      id UUID PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE,
      first_name TEXT,
      last_name TEXT,
      company_name TEXT,
      vat_id TEXT,
      address TEXT,
      city TEXT,
      zip_code TEXT,
      updated_at TIMESTAMP WITH TIME ZONE DEFAULT timezone('utc'::text, now()) NOT NULL
    );
    repaired_tables := array_append(repaired_tables, 'profiles');
  END IF;

  -- 2. end_customers table
  IF NOT EXISTS (SELECT 1 FROM pg_tables WHERE schemaname = 'public' AND tablename = 'end_customers') THEN
    CREATE TABLE public.end_customers (
      id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
      partner_id UUID NOT NULL REFERENCES public.profiles(id) ON DELETE CASCADE,
      company_name TEXT NOT NULL,
      vat_id TEXT,
      first_name TEXT,
      last_name TEXT,
      street TEXT,
      zip TEXT,
      city TEXT,
      is_anonymized BOOLEAN NOT NULL DEFAULT false,
      created_at TIMESTAMPTZ NOT NULL DEFAULT now()
    );
    repaired_tables := array_append(repaired_tables, 'end_customers');
  END IF;

  -- 3. pos_modules table
  IF NOT EXISTS (SELECT 1 FROM pg_tables WHERE schemaname = 'public' AND tablename = 'pos_modules') THEN
    CREATE TABLE public.pos_modules (
      id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
      name TEXT NOT NULL,
      price NUMERIC(10, 2) NOT NULL DEFAULT 0.00,
      created_at TIMESTAMPTZ NOT NULL DEFAULT now()
    );
    repaired_tables := array_append(repaired_tables, 'pos_modules');
  END IF;

  -- 4. licenses table
  IF NOT EXISTS (SELECT 1 FROM pg_tables WHERE schemaname = 'public' AND tablename = 'licenses') THEN
    CREATE TABLE public.licenses (
      id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
      end_customer_id UUID REFERENCES public.end_customers(id) ON DELETE CASCADE,
      pos_module_id UUID REFERENCES public.pos_modules(id) ON DELETE CASCADE,
      license_key TEXT NOT NULL UNIQUE,
      created_at TIMESTAMPTZ NOT NULL DEFAULT now()
    );
    repaired_tables := array_append(repaired_tables, 'licenses');
  END IF;

  -- Enable RLS on all tables
  ALTER TABLE public.profiles ENABLE ROW LEVEL SECURITY;
  ALTER TABLE public.end_customers ENABLE ROW LEVEL SECURITY;
  ALTER TABLE public.pos_modules ENABLE ROW LEVEL SECURITY;
  ALTER TABLE public.licenses ENABLE ROW LEVEL SECURITY;

  -- Recreate RLS Policies
  
  -- profiles Policies
  DROP POLICY IF EXISTS "Users can view their own profile" ON public.profiles;
  CREATE POLICY "Users can view their own profile" ON public.profiles FOR SELECT USING (auth.uid() = id);
  DROP POLICY IF EXISTS "Users can update their own profile" ON public.profiles;
  CREATE POLICY "Users can update their own profile" ON public.profiles FOR UPDATE USING (auth.uid() = id);
  DROP POLICY IF EXISTS "Users can insert their own profile" ON public.profiles;
  CREATE POLICY "Users can insert their own profile" ON public.profiles FOR INSERT WITH CHECK (auth.uid() = id);
  DROP POLICY IF EXISTS "Admins can view all profiles" ON public.profiles;
  CREATE POLICY "Admins can view all profiles" ON public.profiles FOR SELECT USING (auth.role() = 'authenticated');

  -- end_customers Policies
  DROP POLICY IF EXISTS "Partner sehen nur eigene Endkunden" ON public.end_customers;
  CREATE POLICY "Partner sehen nur eigene Endkunden" ON public.end_customers FOR ALL USING (auth.uid() = partner_id) WITH CHECK (auth.uid() = partner_id);

  -- pos_modules Policies
  DROP POLICY IF EXISTS "Allow authenticated read on pos_modules" ON public.pos_modules;
  CREATE POLICY "Allow authenticated read on pos_modules" ON public.pos_modules FOR SELECT USING (auth.role() = 'authenticated');

  -- licenses Policies
  DROP POLICY IF EXISTS "Partner sehen Lizenzen eigener Kunden" ON public.licenses;
  CREATE POLICY "Partner sehen Lizenzen eigener Kunden" ON public.licenses FOR SELECT USING (
    EXISTS (
      SELECT 1 FROM public.end_customers c
      WHERE c.id = licenses.end_customer_id AND c.partner_id = auth.uid()
    )
  );
  DROP POLICY IF EXISTS "Partner erstellen Lizenzen eigener Kunden" ON public.licenses;
  CREATE POLICY "Partner erstellen Lizenzen eigener Kunden" ON public.licenses FOR INSERT WITH CHECK (
    EXISTS (
      SELECT 1 FROM public.end_customers c
      WHERE c.id = licenses.end_customer_id AND c.partner_id = auth.uid()
    )
  );

  result := jsonb_build_object(
    'repaired', to_jsonb(repaired_tables),
    'success', true
  );
  RETURN result;
END;
$$ LANGUAGE plpgsql;

-- CREATE FUNCTION public.optimize_database_indices
CREATE OR REPLACE FUNCTION public.optimize_database_indices()
RETURNS jsonb
SECURITY DEFINER
AS $$
BEGIN
  REINDEX SCHEMA public;
  RETURN jsonb_build_object('success', true, 'message', 'Schema public successfully reindexed.');
END;
$$ LANGUAGE plpgsql;
